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.
![]() | ![]() |
|---|---|
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 base | plot_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
| Fuente | Qué abre |
|---|---|
synthetic | Unidades simuladas ajustadas a la velocidad del cursor, con señal de banda ancha y verdad de referencia |
nwb | Un archivo .nwb local (params.path) |
wav_dir | WAV de banda ancha local (params.path): una carpeta de clips mono, un canal cada uno, o un archivo multicanal |
lsl | Una 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 |
dandi | Un archivo NWB transmitido desde el Archivo DANDI mediante solicitudes de rango HTTP; no se refleja nada |
n1_stub | No 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
| Herramienta | Propósito |
|---|---|
list_sources | Tipos de fuente y sus parámetros |
search_datasets | Buscar en DANDI, o listar conjuntos de datos intracorticales curados |
list_dataset_files | Licencia, cita y archivos NWB de un conjunto de datos DANDI |
list_lsl_streams | Transmisiones LSL visibles en la red |
get_stream_status | Para una sesión en vivo: intervalo almacenado en búfer, si llegan datos, pérdidas |
open_session / close_session | Ciclo de vida de la sesión |
get_session_info | Canales, tasas, señales de comportamiento, licencia, cita |
get_signal_quality | Ruido, SNR, canales muertos/ruidosos |
detect_spikes | Cruces de umbral; precisión/recuperación cuando existe verdad |
sort_spikes | Ordenar 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_geometry | Proporcionar posiciones de contacto para una sesión cuyo archivo no tiene ninguna: diseños Utah, cuadrícula, lineal, tetrodo o coordenadas explícitas |
get_probe | Posiciones de contacto y etiquetas de área cerebral por canal |
plot_probe | Figura: mapa de matriz, contactos coloreados por tasa de disparo, unidades ordenadas por contacto |
get_firing_rates | Resumen de tasa de población |
fit_decoder | Ridge o Kalman, puntuado en datos reservados; hiperparámetros elegidos dentro de la división de entrenamiento |
decode_window | Vista previa decodificado-vs-real para una ventana |
evaluate_cross_session | Ajustar en una sesión, puntuar sin cambios en otras: ¿sobrevive un decodificador a un día posterior? Respeta el eval_mask de FALCON |
get_psth | Disparo alineado a un evento de ensayo, opcionalmente agrupado por una columna de ensayo o limitado a algunas unidades |
fit_latent_factors | GPFA (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_factors | Figura: los tres factores principales a lo largo del tiempo, el espacio de estados factor-1/factor-2 y varianza por factor |
plot_psth | Figura: PSTH por grupo con SEM, sobre un mapa de calor unidad-por-tiempo del cambio respecto a la línea base |
plot_raster | Figura: raster de picos, intervalos no grabados sombreados |
plot_decoding | Figura: 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
| Extra | Añade | Instalación |
|---|---|---|
lsl | la fuente en vivo lsl | uvx --with 'ephys-mcp[lsl]' ephys-mcp |
sort | sort_spikes mediante los ordenadores integrados de spikeinterface (spykingcircus2, tridesclous2); alrededor de 330 MB de dependencias | uvx --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
NeuralSourceno 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.

