ephys-mcp

Análisis de solo lectura de grabaciones de BCI intracorticales (NWB, DANDI, WAV): picos, PSTH, decodificación, gráficos.

Documentación

ephys-mcp

Un servidor MCP que permite a un LLM analizar grabaciones intracorticales (a nivel de picos) de interfaces cerebro-computadora: calidad de señal, detección de picos, tasas de disparo y decodificación de velocidad del cursor.

Los servidores MCP existentes para BCI se centran en EEG de cuero cabelludo. Este se centra en el tipo de datos que produce un implante de alto número de canales, y define un contrato de adaptador de solo lectura para que se pueda añadir un backend de dispositivo en vivo cuando un proveedor publique una API.

Software de investigación y educación. No es un dispositivo médico. No es para uso clínico. No está afiliado ni respaldado por Neuralink Corp. ni por ningún otro fabricante de implantes.

Ejemplo de salida

Figuras de la fuente sintética integrada (32 unidades, 300 s, semilla 2), producidas por las propias herramientas de gráficos del servidor.

PSTH by reach directionKalman decoder on held-out data
plot_psth agrupado por dirección de alcance: tasa de población por dirección (media ± SEM sobre 166 ensayos) sobre un mapa de calor unidad-por-tiempo del cambio respecto a la línea baseplot_decoding después de fit_decoder(kind="kalman"): decodificado frente a la velocidad real del cursor en una ventana reservada de 10 s, R² 0.90 (x) y 0.83 (y)

Estado

v0.5. El conjunto de funciones planificado está completo: archivos NWB locales, grabaciones WAV de banda ancha locales, transmisiones en vivo de Lab Streaming Layer, transmisión desde el Archivo DANDI, una fuente sintética de corteza motora con verdad de referencia, detección de picos, métricas de calidad, decodificadores ridge y Kalman, PSTH alineados por ensayo, ordenamiento de picos, evaluación entre sesiones (estilo FALCON), modelos de factores latentes (GPFA, PCA), geometría de sondas y figuras. 24 herramientas. Los informes de errores y las solicitudes de funciones van a GitHub Issues.

Instalación y ejecución

Requiere uv. Sin paso de instalación: uvx ephys-mcp obtiene el paquete e inicia el servidor en stdio.

Claude Code:

claude mcp add ephys -- uvx ephys-mcp

Claude Desktop (claude_desktop_config.json):

{ "mcpServers": { "ephys": { "command": "uvx", "args": ["ephys-mcp"] } } }

Desde un checkout, usa uv run ephys-mcp en su lugar, o uv --directory /path/to/ephys-mcp run ephys-mcp en las configuraciones anteriores.

Transporte HTTP

Para clientes remotos o agentes alojados, sirve HTTP transmisible en lugar de stdio:

EPHYS_MCP_TOKEN='a-long-random-secret' uvx ephys-mcp --http --host 0.0.0.0 --port 8000

Cada solicitud debe llevar Authorization: Bearer <token>. El servidor se niega a vincularse a una dirección que no sea de bucle local sin un token, y los tokens deben tener al menos 16 caracteres. Coloca TLS delante (un proxy inverso) antes de exponerlo más allá de una red privada: el token viaja en texto claro de lo contrario. En bucle local el token es opcional, por lo que ephys-mcp --http solo sirve http://127.0.0.1:8000/mcp para pruebas locales.

Luego pregunta, para datos reales: "Encuentra un pequeño conjunto de datos de corteza motora en DANDI, ábrelo y dime qué tan bien se puede decodificar la velocidad de la mano." O sin conexión: "Abre una sesión sintética, verifica la calidad de la señal, ajusta un decodificador Kalman y muéstrame una ventana decodificada."

Fuentes de datos

FuenteQué abre
syntheticUnidades simuladas ajustadas a la velocidad del cursor, con señal de banda ancha y verdad de referencia
nwbUn archivo .nwb local (params.path)
wav_dirWAV de banda ancha local (params.path): una carpeta de clips mono, un canal cada uno, o un archivo multicanal
lslUna transmisión de banda ancha Lab Streaming Layer en vivo en la red local; conserva los buffer_s más recientes de señal. Necesita uvx --with 'ephys-mcp[lsl]' ephys-mcp
dandiUn archivo NWB transmitido desde el Archivo DANDI mediante solicitudes de rango HTTP; no se refleja nada
n1_stubNo implementado. Documenta cómo se escribiría un adaptador de implante en vivo sobre la misma base que lsl

La licencia y la cita del conjunto de datos provienen del archivo y son devueltas por open_session, para que el modelo pueda atribuir los datos. Muchos conjuntos de datos registran solo durante ensayos; el servidor rastrea esos intervalos (recorded_fraction) y deja los vacíos fuera de las tasas y la decodificación en lugar de leerlos como silencio.

Las muestras WAV no llevan unidad física, por lo que las amplitudes se informan como recuentos de ADC a menos que pases uv_per_count; cada resultado de amplitud nombra su unidad. Los clips en una carpeta son grabaciones separadas, por lo que el servidor dice que la sincronización entre esos canales no es significativa. Los tiempos de picos de WAV son cruces de umbral, no unidades ordenadas.

Resultados de referencia, todos líneas base causales lineales simples en lugar de estado del arte:

  • MC_Maze_Small (DANDI 000140, 142 unidades, último 20% reservado, bins de 50 ms): ridge R² 0.50, Kalman R² 0.34 para velocidad de la mano.
  • FALCON H1 (DANDI 000954, velocidad humana de 7 grados de libertad, 176 canales, bins de 20 ms, eval_mask): ridge entrenado en el primer día retenido puntúa R² 0.43 en el minival de ese día, 0.07 una semana después y por debajo de cero en los días retenidos. Ese decaimiento es el punto del punto de referencia; el filtro de Kalman no es adecuado para estos datos de calibración guionizados. Las etiquetas de prueba oficiales de FALCON son privadas, por lo que estos no son puntuaciones de tabla de clasificación.

Los hiperparámetros del decodificador (fuerza ridge, el desfase neural para Kalman) se eligen mediante validación cruzada bloqueada dentro de la división de entrenamiento. El historial ridge es de 0.5 s de recuentos de picos independientemente del tamaño del bin.

GPFA se implementa a partir de las ecuaciones del artículo en numpy y scipy (EM sobre cargas, compensaciones, ruido y escalas de tiempo por factor; sin dependencia de aprendizaje profundo), y se ejecuta en segundos en cien ensayos. En el simulador, cuyo latente verdadero es la velocidad del cursor en 2-D, encuentra dos factores dominantes que explican la velocidad con R² 0.95 (PCA: 0.68). En MC_Maze_Small muestra la trayectoria poblacional rotatoria alrededor del inicio del movimiento por la que se conoce a la corteza motora. Los modelos de clase LFADS están fuera de alcance: necesitan una ejecución de entrenamiento de minutos y una pila de aprendizaje profundo.

Herramientas

HerramientaPropósito
list_sourcesTipos de fuente y sus parámetros
search_datasetsBuscar en DANDI, o listar conjuntos de datos intracorticales curados
list_dataset_filesLicencia, cita y archivos NWB de un conjunto de datos DANDI
list_lsl_streamsTransmisiones LSL visibles en la red
get_stream_statusPara una sesión en vivo: intervalo almacenado en búfer, si llegan datos, pérdidas
open_session / close_sessionCiclo de vida de la sesión
get_session_infoCanales, tasas, señales de comportamiento, licencia, cita
get_signal_qualityRuido, SNR, canales muertos/ruidosos
detect_spikesCruces de umbral; precisión/recuperación cuando existe verdad
sort_spikesOrdenar picos de una ventana de banda ancha con spikeinterface (extra sort), usando geometría de sonda cuando se conoce; la sesión luego usa las unidades ordenadas
set_probe_geometryProporcionar posiciones de contacto para una sesión cuyo archivo no tiene ninguna: diseños Utah, cuadrícula, lineal, tetrodo o coordenadas explícitas
get_probePosiciones de contacto y etiquetas de área cerebral por canal
plot_probeFigura: mapa de matriz, contactos coloreados por tasa de disparo, unidades ordenadas por contacto
get_firing_ratesResumen de tasa de población
fit_decoderRidge o Kalman, puntuado en datos reservados; hiperparámetros elegidos dentro de la división de entrenamiento
decode_windowVista previa decodificado-vs-real para una ventana
evaluate_cross_sessionAjustar en una sesión, puntuar sin cambios en otras: ¿sobrevive un decodificador a un día posterior? Respeta el eval_mask de FALCON
get_psthDisparo alineado a un evento de ensayo, opcionalmente agrupado por una columna de ensayo o limitado a algunas unidades
fit_latent_factorsGPFA (Yu et al. 2009) o PCA en actividad alineada por ensayo: trayectorias latentes de un solo ensayo, varianza por factor, escalas de tiempo y qué tan bien explican los factores principales una señal de velocidad
plot_latent_factorsFigura: los tres factores principales a lo largo del tiempo, el espacio de estados factor-1/factor-2 y varianza por factor
plot_psthFigura: PSTH por grupo con SEM, sobre un mapa de calor unidad-por-tiempo del cambio respecto a la línea base
plot_rasterFigura: raster de picos, intervalos no grabados sombreados
plot_decodingFigura: decodificado frente a comportamiento real, un panel por dimensión

Recurso: ephys://sessions. Prompts: analyze_session, falcon_evaluate.

Las herramientas devuelven resúmenes, nunca matrices sin procesar, para que los resultados quepan en el contexto de un modelo.

Extras opcionales

ExtraAñadeInstalación
lslla fuente en vivo lsluvx --with 'ephys-mcp[lsl]' ephys-mcp
sortsort_spikes mediante los ordenadores integrados de spikeinterface (spykingcircus2, tridesclous2); alrededor de 330 MB de dependenciasuvx --with 'ephys-mcp[sort]' ephys-mcp

El ordenamiento usa la geometría de sonda de la sesión, de la tabla de electrodos del archivo o de set_probe_geometry, por lo que los contactos separados por menos de 100 µm se ordenan conjuntamente. Esto importa en sondas densas: en una sonda laminar simulada de 20 µm, ordenar con la geometría verdadera encuentra las 12 unidades reales, mientras que tratar los contactos como independientes informa 15, contando la misma unidad nuevamente en contactos vecinos. Sin geometría, los canales se colocan muy separados y se tratan como electrodos aislados. En el simulador, spykingcircus2 recupera cada unidad con recuperación superior a 0.95.

Las etiquetas de área cerebral provienen de la tabla de electrodos NWB cuando está presente (MC_Maze informa PMd y M1); get_probe las lista por canal para que un análisis pueda restringirse a un área con el argumento units. Ten en cuenta que ninguno de los conjuntos de datos DANDI probados hasta ahora almacena coordenadas de contacto, por lo que para esos set_probe_geometry es la forma de proporcionar un diseño de matriz.

Las herramientas de gráficos devuelven el PNG en línea, para que un modelo con capacidad de visión pueda leer la figura, y también lo guardan en ~/.cache/ephys-mcp/plots (anula con EPHYS_MCP_OUTPUT_DIR). Las figuras usan una paleta categórica verificada para separación de daltonismo, con etiquetas directas para que la identidad nunca dependa solo del color.

Reglas de diseño

  • Solo lectura. El contrato NeuralSource no tiene método de escritura, estimulación o configuración. No se añadirá ninguno sin un diseño de seguridad separado.
  • Local por defecto. Transporte stdio, sin telemetría. HTTP es opcional y protegido por token. Los datos neuronales son sensibles.
  • Sin datos de terceros incluidos. Ver DATA_LICENSES.md.

Escribir un adaptador de fuente

Para grabaciones, subclase ephys_mcp.sources.base.NeuralSource (info, read_raw, spike_times, behavior). Para un dispositivo en vivo, subclase ephys_mcp.sources.live.RingBufferSource y llama a push(samples) desde un hilo de lectura; sources/lsl.py es un ejemplo completo en unas 60 líneas, y sources/n1_stub.py enumera lo que un adaptador de implante necesitaría adicionalmente. Registra la clase en ephys_mcp/sources/__init__.py.

Las sesiones en vivo informan el tiempo como segundos desde la apertura, y solo se puede leer el búfer más reciente, por lo que t_start_s y duration_s avanzan.

Desarrollo

uv run pytest              # offline
uv run pytest -m network   # also streams a real file from DANDI
uv run ruff check .

Cita

Ver CITATION.cff; el botón "Cite this repository" de GitHub lo usa. Cita los conjuntos de datos que analices por separado: get_session_info devuelve la cita de cada uno.

Licencia

CC0 1.0 Universal. Los autores renuncian a todos los derechos de autor y derechos relacionados en la medida en que la ley lo permita. Úsalo para cualquier cosa, sin atribución requerida. CC0 no otorga derechos de patente ni de marca.