Los procesos MCP huérfanos todavía pueden dejar trabajo pendiente
Los procesos MCP huérfanos necesitan algo más que un comando de terminación. Encuentra servidores stdio obsoletos, revoca su autoridad y vincula sus últimas llamadas con la sesión propietaria.

Un fallo del cliente no te dice si su servidor MCP se detuvo. Solo indica que un proceso terminó, o al menos dejó de responder. La diferencia importa porque stdio es un transporte, no un interruptor que detenga el trabajo que ya ha cruzado los límites entre procesos.
He visto equipos tratar un montón de procesos auxiliares antiguos como un simple problema de mantenimiento y descubrir después que uno todavía conservaba un token de nube, un socket de control SSH o una cola de trabajo que nadie había vinculado con la ejecución fallida. El comando de limpieza era sencillo. Lo que habían omitido era reconstruir quién autorizó la última acción.
La respuesta correcta tiene tres tareas distintas: identificar con precisión el proceso sobrante, demostrar si todavía tiene una vía para actuar y conservar el registro que vincula sus últimas llamadas con la sesión a la que pertenecían. Hazlo en ese orden. Terminar primero el proceso puede eliminar la molestia, pero también puede borrar las mejores pruebas de lo ocurrido.
Un proceso sin padre es una pista, no un veredicto
Un proceso huérfano es un proceso secundario cuyo padre original terminó y cuyo padre en el sistema operativo cambió, a menudo a PID 1. Es una prueba útil, pero no define por sí sola que un servidor MCP sea inseguro. Los gestores de procesos, las shells, los IDE y los servicios de lanzamiento pueden reasignar procesos secundarios que funcionan correctamente durante una operación normal.
En un servidor MCP stdio, formula una pregunta más concreta: ¿este proceso todavía pertenece a una conexión activa con el cliente o sobrevivió después de que desapareciera el cliente propietario de su entrada y salida estándar? Para responderla hay que combinar la ascendencia del proceso con los descriptores abiertos, el tiempo transcurrido y un registro de actividad.
La documentación del Model Context Protocol describe stdio como una integración local iniciada mediante un proceso. El cliente inicia un comando e intercambia JSON-RPC delimitado por saltos de línea a través de la entrada y la salida estándar del servidor. Este diseño proporciona a un servidor bien implementado una señal sencilla de finalización: cuando su entrada llega a EOF, el lado del cliente ya no está.
EOF demuestra que el transporte se ha roto o cerrado. No demuestra que todos los trabajadores, procesos secundarios, conexiones de red, temporizadores o trabajos remotos se hayan detenido. Un servidor puede recibir una llamada de herramienta, empezar a trabajar y perder después el cliente antes de producir una respuesta JSON-RPC. Si el controlador inició un subproceso o envió una solicitud a un sistema remoto, ese trabajo puede tener su propio ciclo de vida.
Aquí es donde suelen confundirse dos fallos distintos:
- Un huérfano del sistema operativo ha perdido a su padre original o se ha separado del árbol de procesos esperado.
- Un huérfano lógico ha perdido la sesión que daba sentido a su trabajo, aunque su PID padre todavía parezca normal.
El primero puede desperdiciar memoria o mantener un puerto abierto. El segundo puede provocar un cambio externo no deseado. Hay que revisar ambos.
Un proceso con PPID 1, mucho tiempo transcurrido y sin stdin abierto resulta sospechoso. Un proceso que sigue conectado a una terminal activa también puede ser peligroso si su cliente propietario se ha bloqueado silenciosamente y el proceso tiene una credencial o una conexión reutilizable. A la inversa, un proceso que permanece después de un fallo puede ser inofensivo si no tiene autoridad ni acceso a ningún canal de acción.
No construyas una regla que diga «PPID 1 significa que hay que terminarlo». Construye un registro que explique por qué existe el proceso, qué ejecución lo creó, a qué puede acceder todavía y qué hiciste con él.
Empieza con un inventario de procesos que puedas defender
Toma una instantánea antes de enviar cualquier señal. Después de terminar el proceso no podrás recuperar la línea de comandos, el grupo de procesos ni los descriptores abiertos, y la reutilización de los PID convierte rápidamente unas notas incompletas en conjeturas.
En macOS, empieza con una vista completa en lugar de usar una línea ingeniosa que filtre las pruebas que necesitas:
ps -axo user,pid,ppid,pgid,stat,etime,command
Busca los comandos que inicia tu cliente MCP. Puede tratarse de un binario de servidor directo, un intérprete como node o python, un lanzador de paquetes, un auxiliar SSH o el complemento sp mcp. Copia las filas relevantes en una nota del incidente antes de limitar la búsqueda.
Cada campo responde a una pregunta distinta:
pididentifica el proceso solo para esta inspección.ppidindica si su padre inmediato todavía existe.pgididentifica el grupo de procesos y suele revelar procesos auxiliares hermanos iniciados juntos.statpuede mostrar si el proceso está dormido, detenido o bloqueado en una operación que no se puede interrumpir.etimemuestra si una ejecución supuestamente reciente lleva horas o días activa.commandsuele ser el único registro que queda del ejecutable y los argumentos usados para iniciarlo.
Después inspecciona cada candidato directamente. Sustituye el PID real y guarda la salida con una marca de tiempo en el registro del incidente.
ps -o pid=,ppid=,pgid=,stat=,etime=,user=,command= -p 48271
lsof -nP -p 48271
El primer comando te proporciona un registro de identidad compacto. El segundo indica qué mantiene abierto el proceso. Presta especial atención a los descriptores 0, 1 y 2. Un servidor stdio normal suele tener un extremo de lectura para stdin y extremos de escritura para stdout y stderr. Si stdin ha llegado a EOF, el proceso puede seguir mostrando un descriptor de tubería, así que no deduzcas que está activo solo por su presencia. Busca el panorama completo: proceso conectado, terminales, archivos normales, sockets Unix, conexiones TCP y procesos secundarios.
lsof también puede revelar un error que las listas de procesos ocultan. Supón que el padre del servidor ha desaparecido, pero el servidor todavía tiene una conexión TCP establecida con una API interna. Eso no demuestra que pueda hacer una nueva solicitud, pero sí te da una capacidad concreta que investigar. Si tiene un socket de control SSH o un socket Unix local conectado a un auxiliar de credenciales, considéralo una pista, no una razón para dar por hecho que es seguro.
Comprueba el grupo de procesos antes de actuar:
ps -axo pid,ppid,pgid,stat,etime,command | awk '$3 == 48271 || $2 == 48271'
Este ejemplo supone que 48271 es el ID de grupo que has observado. Ajústalo al valor real. La salida puede mostrar un envoltorio, un servidor y un proceso auxiliar secundario que un kill sencillo contra un solo PID dejaría activos. También puede demostrar que un proceso no tiene hermanos y que resulta más fácil aislarlo.
Evita un atajo habitual: buscar solo node, python o npx y terminar todas las coincidencias. Esos nombres son entornos de ejecución, no identidades. Una limpieza amplia puede romper una extensión del editor, una ejecución de pruebas local, una tarea de compilación o una automatización no relacionada. Compara la línea de comandos completa con la configuración de servidor esperada y revisa después el padre y el grupo que la rodean.
Si tu cliente registra el comando del servidor al iniciarlo, guarda ese comando junto al registro de sesión. Una investigación posterior pasará de ser una búsqueda imprecisa por nombre de proceso a una comparación directa.
La tubería stdio no define el límite de la acción
Un servidor stdio bien escrito debería dejar de aceptar solicitudes cuando stdin se cierra. Debe cancelar el trabajo que no haya comenzado, cerrar el transporte y salir después de realizar cualquier limpieza acotada. La guía oficial del SDK de MCP para TypeScript señala lo mismo al hablar del apagado: cerrar un transporte no drena automáticamente los controladores de herramientas en curso antes de que termine el proceso.
Esta última parte merece más atención. Cuando un cliente falla, un controlador de herramientas puede encontrarse en varios estados:
- No ha iniciado trabajo externo y puede cancelarse limpiamente.
- Ha enviado una solicitud, pero todavía no ha recibido respuesta.
- Ha completado el cambio remoto, pero ha perdido la ruta de respuesta antes de informar del éxito.
- Ha iniciado un proceso secundario local o un trabajo remoto que sobrevive al controlador.
- Está bloqueado esperando una dependencia externa y podría continuar más tarde.
Solo el primer estado puede describirse con seguridad como «no ha ocurrido nada». Los otros cuatro requieren registros fuera del proceso del cliente que ya no funciona.
Considera un ejemplo concreto. Un servidor recibe una llamada de herramienta para desplegar una compilación. Escribe la solicitud en una API remota de compilación y el cliente falla mientras la API la procesa. El servidor detecta que la tubería stdout se ha roto. Si sale de inmediato, la compilación puede seguir ejecutándose. Si reintenta sin un mecanismo de idempotencia, puede iniciar una segunda compilación. Si permanece activo con una credencial de larga duración, puede consultar, reintentar o iniciar trabajo adicional después de que desaparezca el cliente original.
El fallo no consiste en que el servidor haya seguido activo. El fallo consiste en tratar el cierre del transporte como una afirmación completa sobre la autorización, la cancelación y el estado remoto.
Para cada canal de acción, define explícitamente el límite:
- ¿Qué evento impide que entre trabajo nuevo en el servidor?
- ¿Qué identificador permite consultar o cancelar el trabajo ya enviado?
- ¿La operación remota admite idempotencia o un token de solicitud?
- ¿Qué proceso conserva la credencial después de que desaparece el cliente?
- ¿Dónde se registra el resultado final si no se puede entregar la respuesta JSON-RPC?
Si no puedes responder a estas preguntas para una herramienta de alto impacto, no la consideres segura solo porque usa stdio.
La misma regla se aplica a SSH. Un comando que parece interactivo puede haber iniciado un proceso en segundo plano en el host remoto. Cerrar el cliente local puede cerrar el canal local mientras un comando remoto separado de su shell continúa. El servidor necesita un diseño de comandos que haga observable y cancelable el trabajo remoto, no confiar en que la desconexión de la terminal lo detenga.
Demuestra si el proceso sobrante todavía puede actuar
La existencia de un proceso no equivale a autoridad. Hay que probar la ruta de acción sin provocar una acción real.
Primero identifica dónde reside la autoridad. Un servidor que lee un token de API de su propio entorno tiene un perfil de riesgo distinto al de uno que pide a un agente independiente realizar cada acción. Un servidor con una clave privada SSH en un archivo tiene un perfil distinto al de otro que delega mediante un auxiliar local de corta duración. Escribe la respuesta para el servidor concreto que estás revisando.
Después inspecciona qué mantiene abierto y qué puede alcanzar el proceso. lsof es un punto de partida, pero no revela todas las credenciales en memoria ni todas las sesiones autenticadas. Combínalo con tus propios registros de acciones y, cuando exista, con el registro de auditoría del sistema externo.
Una secuencia de investigación útil es la siguiente:
- Registra el PID candidato, el comando, el PPID, el grupo de procesos y los sockets de red o Unix abiertos.
- Encuentra la acción externa más reciente vinculada a ese proceso o a su sesión.
- Comprueba si se produjo una acción nueva después de la hora del fallo del cliente.
- Revoca o desactiva la ruta de autorización del proceso.
- Observa si el proceso intenta realizar otra acción y si la puerta de enlace la rechaza.
No hagas la prueba pidiendo al servidor huérfano que ejecute una escritura que parezca inofensiva. Muchos sistemas no tienen escrituras realmente inofensivas, y una llamada de prueba puede modificar límites de frecuencia, generar ruido en la auditoría, cambiar el estado o activar una automatización. Prefiere un endpoint de salud o identidad de solo lectura si tu diseño dispone de uno. Mejor aún, valida el rechazo de la puerta de enlace o del agente de credenciales después de revocar el acceso.
Hay una distinción importante: que un proceso todavía tenga acceso de red no significa necesariamente que pueda actuar, y que no tenga una conexión de red visible no significa que no pueda actuar más tarde. La resolución DNS, un proxy, un auxiliar local, un temporizador en cola o un proceso secundario pueden volver a abrir la ruta. Por eso la prueba de revocación importa más que una instantánea de los sockets.
Si el servidor conserva directamente un secreto reutilizable, el alcance de la limpieza debe incluir la rotación o revocación del secreto. Terminar el proceso elimina una copia de la memoria, pero no cambia lo que un atacante, una imagen volcada del proceso o un servicio remoto puede hacer con el mismo secreto. Los equipos suelen evitar la rotación porque genera trabajo. Es comprensible, pero no constituye un argumento de seguridad.
Un modelo basado en una puerta de enlace cambia la investigación. El servidor puede sobrevivir como un proceso no confiable y aun así no poder hacer una nueva llamada protegida porque nunca tuvo la credencial y ya no dispone de una sesión activa aprobada. Sallyport guarda los secretos de API y SSH en su bóveda cifrada y ejecuta la acción directamente, de modo que el agente no recibe el secreto en texto plano ni un valor sustitutivo. Esto reduce el daño que puede causar un proceso stdio perdido, pero aun así debes revocar una ejecución sospechosa en lugar de asumir que un fallo del proceso lo hizo por ti.
El criterio práctico es sencillo: después de revocar la sesión o la ruta de acción, una llamada protegida debe ser rechazada y el rechazo debe quedar registrado. Si no puedes demostrarlo, no has confirmado la contención.
Registra las últimas llamadas antes de que la limpieza cambie la historia
Un registro de incidente necesita identificadores estables, no una narración reconstruida de memoria. Un PID es temporal y puede reutilizarse. La línea de comandos puede cambiar después de una actualización. Un identificador de sesión y un registro de auditoría resistente a manipulaciones proporcionan un ancla mucho mejor.
Como mínimo, crea una fila por cada proceso sospechoso con estos campos:
Observed at:
Client process PID and command:
MCP server PID and command:
Parent PID and process group:
Session identifier:
Authorization state:
Last successful action time:
Last attempted action time:
Action target and operation:
Result or remote job identifier:
Revocation time and operator:
Termination signal and exit result:
Follow-up required:
La pareja más importante es el identificador de sesión y la última acción intentada. Muchos equipos registran solo las llamadas correctas, lo que oculta el momento más revelador de una investigación tras un fallo: la solicitud que salió del equipo local pero nunca recibió un resultado.
Mantén separados tres momentos. Registra cuándo dejó de estar disponible el cliente, cuándo comenzó la última acción conocida del servidor y cuándo revocaste la autoridad. Si usas una sola «hora del incidente», no podrás saber si una llamada ocurrió antes del fallo, durante un intervalo incierto o después de que la contención debería haber surtido efecto.
Conserva también el objetivo de la acción. «Llamó a una API de nube» no basta. Registra la cuenta o la clase de endpoint, el método o la categoría del comando SSH y cualquier identificador de solicitud o trabajo que permita buscar la operación en el servicio remoto. Evita guardar cuerpos de solicitudes sensibles en una nota general del incidente. Necesitas suficiente información para reconciliar el efecto secundario, no una segunda copia de todos los secretos y registros de clientes.
En una puerta de enlace con registros separados de sesiones y actividades, usa ambos. El registro de sesión responde quién ejecutó el proceso del agente y si esa ejecución sigue autorizada. El registro de actividad responde qué llamadas individuales ocurrieron y en qué orden. Son preguntas distintas, y mezclarlas en un único flujo amplio de eventos dificulta responder a ambas bajo presión.
Sallyport genera ambos registros desde un registro de auditoría cifrado y encadenado mediante hashes. Después de capturar las entradas pertinentes de sesión y actividad, ejecuta la comprobación de integridad sin conexión:
sp audit verify
Guarda el resultado exacto del comando junto con el registro del incidente. La verificación no decide si la acción estaba autorizada o si fue prudente. Indica si la cadena de auditoría en la que te basas sigue verificándose sin necesitar acceso a la bóveda. Esta separación resulta útil cuando la persona que revisa el incidente no debería recibir credenciales solo para comprobar el historial.
No esperes a que ocurra un incidente de seguridad formal para practicar este registro. Una revisión rutinaria de un fallo es el momento en que descubres que faltan identificadores de sesión, que los comandos son ambiguos o que los registros solo existen en la máquina que ya no funciona. Corregir esas carencias durante una limpieza tranquila cuesta mucho menos que descubrirlas después de una escritura en producción.
Revoca la autoridad antes de terminar el proceso
El orden más seguro es revocar, verificar el rechazo y después detener el proceso. Invertirlo parece más rápido porque el proceso desaparece de inmediato, pero puede dejar activa una autorización y dificultar la correlación posterior.
Empieza por la revocación efectiva más limitada. Si el sistema registra la autorización por ejecución del agente, revoca esa ejecución. Si una única credencial quedó expuesta al servidor, desactívala o rótala. Si un trabajo remoto tiene un mecanismo de cancelación, cancela ese trabajo por separado. Son acciones distintas porque responden a ciclos de vida distintos.
No supongas que la salida del servidor cancela el trabajo remoto. El proceso puede haber desaparecido mientras su solicitud sigue en cola. Tampoco supongas que una cancelación remota detiene el servidor. Si conserva la autoridad, el proceso puede reintentar o enviar otra solicitud. La contención exige que los lados local y remoto coincidan en que la ejecución ha terminado.
Una vez revocada la ruta de acción, verifica el estado con pruebas adecuadas para tu configuración. Puede tratarse de un rechazo registrado en el diario de actividad de la puerta de enlace, una solicitud autenticada fallida a un endpoint de identidad seguro o una entrada de auditoría remota que muestre que el token se ha desactivado. El método exacto varía. El principio no: demuestra que un proceso superviviente no puede hacer una llamada protegida.
Después envía una señal de terminación normal al PID identificado:
kill -TERM 48271
sleep 2
ps -p 48271 -o pid=,ppid=,stat=,etime=,command=
Si el último comando no devuelve ninguna fila de proceso, registra el resultado. Si el proceso continúa, revisa si se está apagando, si está bloqueado en una operación de entrada y salida o si mantiene activo trabajo secundario. Antes de aumentar la intensidad, vuelve a inspeccionar el grupo y los procesos secundarios. Puede que tengas que terminar por separado un auxiliar conocido, pero no termines a ciegas todo un grupo de procesos sin confirmar que cada miembro pertenece a la misma ejecución fallida.
Usa kill -KILL solo cuando la terminación normal no funcione y hayas conservado las pruebas. SIGKILL no da al proceso ninguna oportunidad de cerrar archivos, cancelar trabajo, emitir un registro final o eliminar el estado temporal. A veces es la decisión correcta. Llámala por lo que es: contención forzada con una posible limpieza incompleta.
Monitor de Actividad de macOS puede ayudar cuando la línea de comandos no basta. Apple documenta una acción normal de salida y otra de salida forzada, y permite mostrar los procesos jerárquicamente. La vista jerárquica sirve para confirmar las relaciones entre padres y procesos secundarios. No sustituye al registro del incidente, porque una lista gráfica no conserva las pruebas de sesión y actividad que necesitarás después.
Convierte el apagado del servidor en un requisito de diseño
Los servidores stdio deben tratar la desaparición del cliente como un evento de primera clase, no como un caso excepcional. Los fallos de los clientes son un comportamiento normal del software. Los portátiles entran en reposo, las terminales se cierran, los IDE se reinician, las actualizaciones interrumpen procesos y los agentes pueden abortar después de un error del modelo.
Un servidor debe tener una ruta de apagado explícita con cuatro propiedades. Deja de aceptar solicitudes nuevas cuando se cierra la entrada. Rastrea cada acción iniciada con un identificador de correlación. Concede al trabajo activo un tiempo limitado para cancelarse o llegar a un estado conocido. Sale después de ese límite, en lugar de convertirse accidentalmente en un servicio permanente en segundo plano.
No confundas un apagado correcto con esperar para siempre. Un servidor que recibe EOF y espera indefinidamente a una API externa es un huérfano con mejores modales. Establece un plazo para la limpieza, registra lo que siga sin resolverse y sal. El trabajo pendiente debe poder descubrirse mediante su identificador de trabajo externo o su registro de acción.
La gestión de procesos secundarios importa tanto como lo anterior. Si una herramienta inicia un compilador, un gestor de paquetes, un auxiliar SSH, un controlador de navegador o un envoltorio de comandos, el servidor debe saber si ese proceso debe morir cuando muera el servidor. Configura los grupos de procesos deliberadamente. Captura los PID de los procesos secundarios. Durante el apagado, termina solo los procesos secundarios que pertenezcan a la solicitud y registra si han salido.
Evita enviar trabajo al segundo plano mediante una shell, salvo que el contrato de la herramienta exija explícitamente un trabajo persistente en segundo plano. Un comando como some-command \u0026 crea un segundo ciclo de vida que tu servidor MCP puede no observar. Si necesitas trabajo persistente, envíalo a un sistema de trabajos que devuelva un ID de trabajo y ofrece herramientas específicas para consultar su estado y cancelarlo. El trabajo oculto en segundo plano no es persistencia. Es una brecha de auditoría.
Usa idempotencia cuando el servicio remoto la admita. Asigna a cada escritura externa un identificador de solicitud derivado de la sesión y de la llamada de herramienta, y registra ese identificador antes de enviar la solicitud. Si el cliente falla después del envío, puedes consultar el sistema remoto en lugar de adivinar si debes reintentar. Cuando no admita idempotencia, documenta la ambigüedad y exige que un operador decida antes de repetir una escritura.
El servidor también debe escribir los diagnósticos en stderr, nunca en stdout. stdout pertenece al flujo JSON-RPC de MCP delimitado por saltos de línea. Una línea de depuración inesperada puede corromper el protocolo, provocar un fallo del cliente y crear precisamente el patrón de fallo que intentas limpiar. Parece un detalle pequeño, hasta que un servidor de producción imprime una advertencia de una biblioteca al iniciarse.
Pon la propiedad en el registro de acciones, no en el historial de la shell
El historial de la shell resulta práctico hasta que falta, se trunca, se comparte o se escribe después de que el proceso muera. El registro de acciones debe llevar la información de propiedad mientras el trabajo está en curso.
Para cada llamada que pueda tocar un sistema externo, adjunta suficiente contexto para responder después a cuatro preguntas: qué ejecución del agente la solicitó, qué proceso local la envió, qué decisión de autorización la permitió y qué operación externa produjo. Si falta cualquiera de estos datos, un fallo del cliente deja un hueco que el investigador tendrá que llenar mediante inferencias.
No sobrecargues la identidad de firma de código con todas las preguntas de propiedad. Indica quién firmó el ejecutable, lo que sirve para decidir si un proceso merece aprobación. No identifica la ejecución concreta, la instrucción que llevó a la llamada ni la solicitud remota. Usa la autoridad de firma de código para la confianza al comenzar la sesión, y después utiliza un identificador de sesión y registros por llamada para la trazabilidad operativa.
La misma advertencia se aplica a las líneas de comandos. Un comando puede indicar que se inició sp mcp o un ejecutable del servidor. No puede indicar de forma fiable cuál fue la última llamada de herramienta, si un usuario la aprobó o si el sistema remoto la aceptó. Trata la lista de procesos como una prueba complementaria, no como la fuente de auditoría.
Cuando ocurre un fallo, correlaciona la información en este orden:
- Encuentra la ejecución del agente que era propietaria del proceso del cliente en el momento del fallo.
- Encuentra el proceso del servidor o el grupo de procesos que inició esa ejecución.
- Localiza las últimas entradas de actividad de esa ejecución y compara sus marcas de tiempo con la instantánea de procesos.
- Reconcilia cualquier operación externa inacabada mediante su identificador de solicitud, transacción o trabajo.
- Registra los eventos de revocación y terminación junto a las últimas llamadas.
Esta secuencia evita un error conocido: encontrar un PID obsoleto, terminarlo y atribuir después su última llamada a la API a la ejecución equivocada del agente porque dos sesiones usaron el mismo comando de servidor. Los comandos se repiten. Los registros de sesión no deberían hacerlo.
Si hoy tu entorno no puede establecer esa correlación, añádela antes de conceder acceso de escritura a herramientas autónomas. La experimentación de solo lectura puede convivir con una observabilidad imperfecta. Los cambios en producción no.
Un simulacro de fallo revela las carencias cuando el riesgo es bajo
Realiza un simulacro de fallo controlado para cada servidor MCP que pueda hacer cambios externos. Hazlo en una cuenta de prueba o mediante una ruta de acción de solo lectura y captura las pruebas como si gestionaras un incidente real.
Inicia una sesión normal del cliente y ejecuta una acción con un identificador de correlación conocido. Mientras el servidor esté activo, termina el cliente de forma abrupta. Después inspecciona el PID del servidor, su PPID y su grupo de procesos, sus descriptores abiertos y el registro de acciones. Revoca la sesión. Confirma que una llamada protegida posterior sea rechazada. Por último, termina el servidor si no salió al recibir EOF y reconcilia la acción externa.
El simulacro debe producir respuestas, no una simple etiqueta de aprobado o suspenso. Debes saber si el cierre de stdin llega al servidor, si los procesos secundarios permanecen activos, si los trabajos remotos tienen mecanismos de cancelación, si los registros identifican al propietario y si la revocación cambia el comportamiento de inmediato.
Presta atención a los tiempos. Un fallo que ocurre antes del envío de la solicitud se comporta de forma distinta a uno que ocurre después de que un servicio remoto haya aceptado la solicitud. Repite el simulacro en ambos puntos si el servidor ofrece suficiente instrumentación. El límite incómodo entre «enviado» y «confirmado» es donde aparecen las escrituras duplicadas y las falsas garantías.
Escribe la expectativa de limpieza para cada servidor. Una buena expectativa es concreta: después de cerrarse la entrada, el servidor deja de aceptar llamadas, sale dentro del tiempo configurado, no deja procesos auxiliares de su propiedad y crea un registro de actividad para cada acción externa iniciada. Una expectativa débil es «normalmente el cliente se encarga de limpiarlo». El comportamiento normal no es un control.
Después de repetirlo varias veces, los procesos obsoletos dejan de ser misteriosos. Se convierten en un modo de fallo definido, con una instantánea del proceso, un rastro de propiedad, una acción de revocación y una regla de limpieza. Ese es el estándar que debes buscar. El proceso puede fallar. Tu capacidad para explicar y contener sus últimas llamadas no debería hacerlo.
FAQ
¿Qué es un proceso MCP huérfano?
Es un proceso de servidor MCP local que sigue activo después de que termina el proceso o la conexión del cliente que lo inició. Un proceso con PPID 1 es una pista útil, pero no constituye una prueba por sí solo, porque los lanzadores y gestores de servicios también pueden reasignar procesos secundarios que funcionan correctamente.
¿Un servidor MCP huérfano todavía puede hacer llamadas a una API?
A veces. Si el servidor tiene un token de API, una credencial SSH, una conexión autenticada reutilizable o un trabajador en segundo plano, podría seguir realizando cambios externos después de que desaparezca el cliente MCP. Un canal stdio cerrado solo termina la conversación del protocolo, no cancela el trabajo que el servidor ya haya delegado en otro lugar.
¿Cómo encuentro servidores MCP obsoletos en macOS?
Empieza por la identidad del proceso, el PID del proceso padre, el grupo de procesos, el tiempo transcurrido, la línea de comandos y los descriptores de archivo abiertos. Después compara la última acción externa observada con tu registro de actividad. Una lista de procesos por sí sola no puede decirte si el proceso todavía tiene autoridad.
¿Debo terminar de inmediato un proceso MCP huérfano?
Usa primero una señal de terminación normal y comprueba después que el PID haya desaparecido y que no queden trabajadores secundarios. Force Quit o SIGKILL solo deberían usarse después de capturar las pruebas y aceptar que una operación en curso podría detenerse a mitad de camino.
¿El ID de sesión MCP es lo mismo que un PID?
No. El ID del proceso identifica un proceso del sistema operativo, mientras que una sesión MCP identifica una ejecución concreta del protocolo. Un mismo cliente puede crear varios procesos de servidor y un proceso que sigue activo puede haberse separado de la sesión que lo autorizó originalmente.
¿Cómo evito que los agentes obsoletos conserven credenciales?
El diseño más seguro mantiene las credenciales fuera del agente y del servidor stdio, y exige una ruta de autorización activa para cada acción. Un proceso puede permanecer en memoria, pero no podrá hacer gran cosa si no puede recuperar un secreto ni enviar una acción aprobada.
¿Qué debe incluir el registro de un incidente por un fallo de MCP?
Registra el proceso del agente, el PID del servidor, el identificador de sesión, la hora de la acción, el objetivo, el método o la categoría del comando, el resultado y la decisión de terminación. Captura esta información antes de limpiar, porque los PID se reutilizan y el historial de la terminal es un registro deficiente para un incidente.
¿La aprobación del cliente caduca cuando se bloquea un cliente MCP?
Si la aprobación pertenece a un proceso de agente que todavía está activo, puede seguir siendo válida hasta que el proceso termine o un operador revoque la sesión. Trata el fallo del cliente como un motivo para revisar la sesión, no como una prueba de que todos los procesos relacionados hayan perdido el permiso.
¿Cómo debe gestionar un servidor MCP stdio los fallos del cliente?
Cierra stdin, trata EOF como un evento de apagado, cancela el trabajo en cola, limita el tiempo de las solicitudes y asegúrate de que los procesos auxiliares terminen junto con su padre. El servidor también debe registrar la identidad de la solicitud antes de iniciar una acción externa, no después de que termine.
¿Cómo puede Sallyport ayudar a investigar un cliente MCP bloqueado?
Usa el registro de sesiones para encontrar y revocar la ejecución, y después utiliza el registro de actividad para exportar o registrar las últimas llamadas anteriores y posteriores al fallo. Ejecuta sp audit verify sobre los datos de auditoría conservados para comprobar que el historial que estás consultando no haya sido alterado.