huckleberry-mcp-worker
huckleberry-mcp-worker
Un servidor del Protocolo de Contexto de Modelo para la aplicación de seguimiento de bebés Huckleberry, ejecutándose como un Cloudflare Worker.
Se trata de una adaptación a TypeScript de
bckenstler/py-huckleberry-mcp.
El original es un servidor stdio de Python que se comunica con Firestore a través de
google-cloud-firestore, el cual utiliza gRPC y, por lo tanto, no puede ejecutarse en Workers.
Esta adaptación accede al mismo backend mediante la API REST de Firebase usando fetch, y
ofrece MCP a través de HTTP Transmisible.
La diferencia práctica: siempre está activo. No es necesario que un portátil esté encendido para que un cliente registre una siesta.
Herramientas
Las 23 herramientas del servidor Python están implementadas, además de delete_record.
Área | Herramientas |
Niños |
|
Sueño |
|
Alimentación |
|
Pañal |
|
Crecimiento |
|
Registros |
|
Cada herramienta de historial informa el interval_id de cada registro, que es lo que
delete_record recibe como parámetro.
Correcciones respecto al servidor Python
Se encontraron cuatro defectos durante la adaptación y se corrigen aquí.
Las duraciones de la lactancia se escribían en la unidad incorrecta. El backend almacena
leftDuration / rightDuration en segundos (que es lo que escribe el temporizador propio de la aplicación), pero log_breastfeeding pasaba directamente los minutos de la persona que llama.
Registrar una toma de 5 minutos grababa 5 segundos. Quienes llamaban tenían que pasar 300
para indicar 5 minutos; aquí left_duration_minutes: 5 significa cinco minutos.
Las consultas de historial de un solo día no devolvían nada. Ambos extremos de un rango de fechas se resolvían a la medianoche, por lo que start_date == end_date producía una ventana vacía y el servidor no informaba registros para un día que sí los tenía. Los rangos ahora son
semiabiertos [start_of_start_date, start_of_end_date + 1 día), haciendo que ambos extremos sean inclusivos.
end_time en el historial de sueño siempre era nulo. El código leía un campo end que el backend nunca escribe. Ahora se deriva de start + duration.
birth_date en list_children siempre era nulo. El campo del backend es
birthdate; el servidor leía birthDate.
get_feeding_history ahora también devuelve el mode de cada registro, junto con los detalles
que lo acompañan: cantidad y tipo para biberones, nombres de alimentos y reacciones para sólidos.
Sin ellos, un registro de sólidos es una fila vacía, indistinguible de una sesión de lactancia de duración cero, que es exactamente cómo un registro perfectamente válido se confunde con uno inexistente.
Configuración
Requiere Node 18+ y una cuenta de Cloudflare.
npm install
npx wrangler loginEstablece los secretos: se almacenan cifrados por Cloudflare y nunca residen en el repositorio:
npx wrangler secret put HUCKLEBERRY_EMAIL
npx wrangler secret put HUCKLEBERRY_PASSWORD
npx wrangler secret put MCP_AUTH_TOKEN # a long random string you generate
npx wrangler secret put HUCKLEBERRY_TIMEZONE # e.g. America/Sao_PauloHUCKLEBERRY_TIMEZONE tiene como valor predeterminado America/New_York. Decide cómo se interpretan las fechas y horas ingenuas como "2026-08-17T15:47:00", por lo que configurarlo correctamente es importante.
Despliegue:
npm run deployAutenticación
La URL del Worker es pública y el servidor tiene credenciales para el registro de salud de un niño, por lo que cada solicitud debe incluir el token de portador:
Authorization: Bearer <MCP_AUTH_TOKEN>Las solicitudes sin un token válido reciben un 401 antes de realizar cualquier llamada a Huckleberry.
Genere un token con algo como openssl rand -base64 32.
Clientes que no pueden enviar cabeceras
Algunos clientes MCP aceptan solo una URL: los conectores personalizados de claude.ai, por ejemplo, toman una URL y credenciales OAuth opcionales sin ningún campo para Authorization. Para esos, el servidor también acepta el token como el último segmento de la ruta:
POST https://<your-worker>.workers.dev/mcp/<MCP_URL_TOKEN>MCP_URL_TOKEN es un secreto distinto de MCP_AUTH_TOKEN, y deliberadamente: las rutas de solicitud terminan en registros de acceso, historial del navegador y referentes de una manera que las cabeceras no. Mantenerlos separados significa que una fuga a través de una URL no compromete la credencial de la cabecera, y cualquiera de las dos puede rotarse de forma independiente. Si MCP_URL_TOKEN no está configurado, la ruta recurre a MCP_AUTH_TOKEN, lo cual es conveniente pero renuncia a esa separación.
npx wrangler secret put MCP_URL_TOKENPrefiera la ruta de la cabecera siempre que el cliente la admita.
Configuración del cliente
Para Claude Code:
claude mcp add --transport http huckleberry https://<your-worker>.workers.dev/mcp \
--header "Authorization: Bearer <MCP_AUTH_TOKEN>"Desarrollo local
cp .dev.vars.example .dev.vars # then fill it in; .dev.vars is gitignored
npm run devcurl -X POST http://localhost:8787/mcp \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'Notas de diseño
Sin estado. Cada solicitud construye un McpServer nuevo a través de createMcpHandler del SDK de agents de Cloudflare. No se utilizan Durable Objects ni almacenamiento de sesión, porque cada herramienta es una lectura o escritura autocontenida.
Caché de tokens. Los tokens de ID de Firebase duran una hora y se almacenan en caché en el ámbito del módulo, por lo que las solicitudes que llegan a un aislado cálido omiten la reautenticación. Un aislado frío cuesta un viaje de ida y vuelta adicional. Un token rechazado durante la ejecución desencadena una reautenticación y un reintento.
Tipos numéricos. Firestore distingue entre enteros y dobles, y la aplicación escribe algunos campos como uno y otros como el otro. Los valores que deben almacenarse como dobles se envuelven en dbl() para que los registros escritos aquí coincidan con los registros escritos por la aplicación.
Documentos con múltiples entradas. El historial se presenta en dos formas: documentos ordinarios con un start de nivel superior y documentos por lotes que contienen muchas entradas bajo data. Los inicios anidados no se pueden filtrar en el servidor, por lo que los documentos por lotes se obtienen completos y se filtran en el Worker. Los registros informan de qué forma provienen mediante is_multi_entry.
Eliminación de registros
El servidor Python no tenía función de eliminar, y la sabiduría popular era que el backend no lo permitía. Sí lo hace: un DELETE en la ruta del documento devuelve 200. Lo que realmente faltaba era el identificador del registro, que las herramientas de historial nunca informaban.
Por lo tanto, las herramientas de historial ahora devuelven interval_id, y delete_record elimina el registro que nombra. Las entradas por lotes (varios registros empaquetados en un documento bajo data) se abordan como <documentId>#<entryKey> y se eliminan como un campo de su padre.
Eliminar también reasigna prefs.last* al registro superviviente más reciente. La aplicación lee esos punteros directamente, por lo que una eliminación sin la reasignación deja mostrando un registro que ya no existe.
Limitaciones conocidas
Las eliminaciones son permanentes. No hay deshacer. Confirme con una consulta de historial antes de llamar a
delete_record.Los sólidos son de solo lectura.
get_feeding_historyinforma entradas de sólidos con sus nombres de alimentos y reacciones, pero no hay ninguna herramienta para crear uno.start_sleepno protege contra un temporizador ya en ejecución. El servidor Python documentó que fallaría en ese caso pero nunca lo comprobó; el comportamiento se conserva aquí en lugar de cambiarlo silenciosamente.Las notas no se reflejan en los registros de sueño. El campo
detailses una estructura fija de casillas de verificación, no texto libre.
Licencia
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Cloud-hosted MCP server for durable AI memory
Hosted remote MCP server for YNAB on Cloudflare Workers with OAuth
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/jcrispiniano/huckleberry-mcp-worker'
If you have feedback or need assistance with the MCP directory API, please join our Discord server