Skylight MCP server
Servidor MCP de Skylight
Permite que un anillo Pebble Index añada eventos por voz a un calendario familiar de Skylight. El agente en la nube de Pebble es el cliente MCP; este servidor se encarga del trabajo HTTP contra la API no oficial de Skylight. Pebble nunca se comunica directamente con Skylight, y Skylight nunca ve tu cuenta de Pebble.
La única herramienta expuesta es create_event (solo escritura: Pebble no necesita volver a leer el calendario, y eliminar list_events mantuvo la superficie de herramientas sin ambigüedades). Puede etiquetar automáticamente un perfil de miembro de la familia predeterminado y entiende "me"/"myself" como esa persona, o cualquier otro miembro por nombre.
Transporte: Streamable HTTP. Autenticación: un token Bearer estático en la cabecera Authorization (Pebble no admite flujos de inicio de sesión OAuth para servidores MCP personalizados, solo una cabecera fija).
¿Es reutilizable para el Pebble + Skylight de otra persona?
Sí: nada en el código está ligado a una persona concreta. Cada valor específico de la cuenta (inicio de sesión de Skylight, id del frame, zona horaria, qué miembro de la familia es el predeterminado, el token Bearer) proviene de una variable de entorno, y los nombres de los miembros de la familia se resuelven en vivo contra las categorías de tu Skylight, no están codificados. Cualquiera con su propia cuenta de Skylight, un Pebble Index y un lugar donde alojar un pequeño servicio HTTP en Python puede ejecutar su propia copia. Ver Despliegue más abajo: es un puñado de comandos de CLI, no una edición manual de código.
Related MCP server: Google Calendar AutoAuth MCP Server
Variables de entorno
Variable | Obligatoria | Descripción |
| sí | Tu correo de inicio de sesión de |
| sí | Tu contraseña de inicio de sesión de |
| sí | El número de |
| sí | Token estático que Pebble envía como |
| no | Zona horaria IANA en la que se interpretan las horas de eventos naive. El valor por defecto es |
| no | El nombre de perfil de un miembro de la familia de Skylight (debe coincidir con una etiqueta de categoría de tu calendario). Se usa cuando se omite |
| no | Lo establece automáticamente Railway/la mayoría de los hosts. El valor por defecto es |
Configuración local
python3 -m venv .venv && source .venv/bin/activate # needs Python 3.10+
pip install -r requirements.txt
cp .env.example .env # then fill in real values
export $(grep -v '^#' .env | xargs) # or use your own env loader
export MCP_BEARER_TOKEN=$(openssl rand -hex 32)
python skylight_mcp_server.pyEl servidor escucha en http://0.0.0.0:8000 (o en $PORT si está definido), el endpoint de MCP en /mcp y la comprobación de salud en /healthz (no requiere autenticación).
Pruebas con MCP Inspector
npx @modelcontextprotocol/inspectorEn la interfaz del Inspector:
Transporte: Streamable HTTP
URL:
http://localhost:8000/mcpEn Autenticación, añade la cabecera
Authorization: Bearer <your MCP_BEARER_TOKEN>Conéctate, luego llama a
create_eventcon un título de prueba y comprueba que llegó al perfil correcto en la aplicación Skylight.
Despliegue en Railway
Opción A: el asistente deploy.sh
export SKYLIGHT_EMAIL=you@example.com
export SKYLIGHT_PASSWORD=...
export SKYLIGHT_FRAME_ID=1234567
export MCP_BEARER_TOKEN=$(openssl rand -hex 32)
# optional:
export SKYLIGHT_TIMEZONE=America/Chicago
export SKYLIGHT_DEFAULT_MEMBER=YourName
./deploy.shInstala la CLI de Railway si no está presente, te pide que inicies sesión (OAuth en el navegador: esta parte no se puede automatizar), crea el proyecto en la primera ejecución, establece todas las variables de entorno, despliega e imprime la URL pública. Vuélvelo a ejecutar en cualquier momento después de editar skylight_mcp_server.py para enviar una nueva compilación: el enlace del proyecto se guarda en ~/.railway/config.json vinculado a este directorio, no en el repositorio, por lo que nada específico de Railway termina en git.
Opción B: a mano
railway login # browser OAuth
railway init --name skylight-mcp # first time only
railway variable set SKYLIGHT_EMAIL=you@example.com --service skylight-mcp --skip-deploys
railway variable set SKYLIGHT_PASSWORD=... --service skylight-mcp --skip-deploys
railway variable set SKYLIGHT_FRAME_ID=1234567 --service skylight-mcp --skip-deploys
railway variable set MCP_BEARER_TOKEN=$(openssl rand -hex 32) --service skylight-mcp
railway up -c -y --service skylight-mcp # builds the Dockerfile, deploys
railway domain --service skylight-mcp # public HTTPS URL, real certVolver a desplegar más tarde (ya seas tú, después de un cambio de código, o cualquier otra persona que ya haya ejecutado la configuración una vez) es simplemente:
railway up -c -y --service skylight-mcpEsa es toda la historia del redespliegue: no hay archivo de configuración más allá del Dockerfile que ya está en este repositorio, ni pipeline de CI. railway logs --service skylight-mcp sigue los logs en vivo, lo cual es útil, ya que los argumentos de create_event se registran en cada llamada (ver Solución de problemas).
Apunta la configuración del cliente MCP de Pebble a https://<your-railway-domain>/mcp con el token Bearer de la configuración.
Configuración de la aplicación Pebble
En los ajustes del servidor MCP de la aplicación Pebble:
Nombre: lo que quieras, pero sin espacios ni caracteres especiales — ver Solución de problemas. Tanto
SkylightCalendarcomoskylight-calendarfuncionan.URL:
https://<your-railway-domain>/mcpTransporte: Streamable (el menú desplegable dice literalmente "SSE/Streamable": elige Streamable, no SSE)
Autorización:
Bearer <your MCP_BEARER_TOKEN>— la cadena completa, incluido el prefijoBearer.
Las herramientas MCP personalizadas solo se ejecutan en el modo de grabación de doble clic de Pebble (el clic simple usa las acciones integradas de Pebble). Asegúrate de que este servidor esté asignado al grupo de sandbox que use tu doble clic.
Cómo funciona el etiquetado de miembros de la familia
Los miembros de la familia no están configurados en este servidor en absoluto: create_event llama a GET /frames/{id}/categories en tu cuenta real de Skylight (almacenado en caché en memoria por proceso) y compara el argumento who con esas etiquetas, sin distinguir mayúsculas de minúsculas. "me"/"myself"/"i" se resuelven a SKYLIGHT_DEFAULT_MEMBER. Si una coincidencia exacta falla, recurre a una coincidencia difusa (difflib) con las mismas etiquetas, ya que el reconocimiento de voz de Pebble puede distorsionar nombres menos comunes (p. ej., tanto "Metree" como "May Tree" siguen resolviéndose a "Maitree" — verificado en vivo). Los nombres que siguen sin coincidir con nada no bloquean el evento: se crea sin etiqueta de perfil, y la confirmación lo indica, de modo que un error de audición es visible en lugar de ser silenciosamente incorrecto.
Frases de ejemplo para probar
Cada una ejercita una parte diferente de la herramienta: después de decir una (doble clic en el anillo), revisa en Skylight la fecha/hora, si es de día completo o con hora, y qué perfil(es) se etiquetaron:
"Añade una cita con el dentista mañana a las 2 p. m." Evento con hora, usa el perfil de
SKYLIGHT_DEFAULT_MEMBERpor defecto, sin ubicación."Bloquea el próximo lunes como día de vacaciones." No se dice ninguna hora → se guarda como un evento de día completo (se detecta automáticamente a partir de la fecha sola: no necesitas decir "todo el día" para que funcione).
"Añade un viaje a Chicago del 2 al 3 de septiembre." Evento de día completo de varios días: abarca ambos días de forma inclusiva.
"Añade el corte de pelo de Maitree el próximo martes a las 10 a. m."
whoexplícito: etiqueta el perfil de esa persona en lugar del predeterminado."Añade la noche de cine en familia el viernes a las 7 p. m. para Maitree y para mí." Etiquetado de varias personas: se guarda etiquetado para ambos.
"Añade una cita con el dentista en el consultorio del Dr. Smith el próximo miércoles a las 3 p. m." Prueba la captura del campo
location.
Qué está verificado frente a lo asumido
La API de Skylight no es oficial y ha sido sometida a ingeniería inversa. El flujo de autenticación y las formas de los payloads de este servidor se probaron en vivo contra una cuenta real el 2026-08-26/27 (consulta el docstring del módulo en skylight_mcp_server.py para conocer los pasos exactos de inicio de sesión). Hallazgos notables que contradecían las suposiciones iniciales extraídas de una captura de OpenAPI de diciembre de 2025:
El antiguo inicio de sesión
POST /api/sessions(correo/contraseña → autenticación Basic) está retirado: ahora devuelve 401 "This version of Skylight is no longer supported." El flujo real es un intercambio de código de autorización OAuth2 de 4 pasos (no se requiere PKCE para que este flujo tenga éxito, aunque también existe una variante con PKCE en el mundo real).skylight-api-version: 2026-05-01es obligatorio en cada llamada a la API.date_maxenGET .../calendar_eventses un límite superior exclusivo.El
ends_atde los eventos de día completo también es exclusivo: un evento de día completo de un solo día necesitaends_ata la medianoche del siguiente día (o, de forma equivalente, igual astarts_at, que también funciona), y un período de N días necesitaends_atampliado un día más allá del último día inclusivo.create_eventmaneja esta ampliación internamente para que su propio argumentoendsiga siendo inclusivo para quien lo llama.Los miembros de la familia se etiquetan mediante
category_ids(un array) en el payload de creación; los ids de categoría provienen deGET .../categoriesy se almacenan en caché por proceso.
Si Skylight vuelve a cambiar su API, estos son los lugares con más probabilidades de romperse: _login() (los pasos de OAuth) y la forma del payload de calendar_events en create_event.
Solución de problemas
Pebble dice "invalid tool call, action failed" y no llega nada al calendario. Revisa primero railway logs --service skylight-mcp — cada llamada a create_event registra sus argumentos sin procesar, y los fallos de la API de Skylight también se capturan y registran. Dos cosas con las que este proyecto ya se ha encontrado:
El nombre del servidor MCP tiene un espacio o un carácter especial en la configuración de la aplicación Pebble. Confirmado en el foro de Pebble: un espacio en el campo
Namedel servidor hace que el agente construya un nombre de herramienta compuesto incorrecto y la llamada nunca llega al servidor, sin que se genere ningún error visible (verásListToolsRequesten los logs pero ningúnCallToolRequest). Renómbralo para que contenga únicamente caracteres alfanuméricos y guiones.Argumentos opcionales de herramienta tipados como anulables (
str | None). Algunos validadores estrictos de llamadas a funciones rechazan un esquema JSON conanyOf: [string, null]antes siquiera de enviar la solicitud. Este servidor usa en su lugarstr = ""simple (cadena vacía = "no proporcionado"), específicamente para evitar eso.
No se pudo parsear una fecha/hora. create_event captura esto y devuelve una cadena de error descriptiva (visible dondequiera que Pebble muestre los resultados de la herramienta) en lugar de fallar, indicando exactamente qué no pudo parsear.
Un evento se guardó a una hora incorrecta (p. ej., 2 a. m.). Casi con seguridad es una confusión entre hora naive y UTC. El manejo de horas naive de create_event siempre asume SKYLIGHT_TIMEZONE, nunca UTC: si ves esto, comprueba si Pebble envió por error una hora UTC sin zona horaria (revisa el argumento start sin procesar en los logs).
Verificación de la comprobación del token Bearer
# No token -> 401
curl -i https://<your-railway-domain>/healthz # should be 200, no auth needed
curl -i https://<your-railway-domain>/mcp # should be 401
# With token -> reaches the MCP layer
curl -i https://<your-railway-domain>/mcp \
-H "Authorization: Bearer <your MCP_BEARER_TOKEN>" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2026-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'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
Connects ChatGPT to your Apple Calendar via a local Mac agent + Vercel relay
Read tasks, habits, events and scheduling links; create and update Reclaim tasks and habits.
Calendar API for AI agents: events, availability, Google/Microsoft setup, scheduling, and iCal.
GDPR-compliant calendar access for AI assistants. Google, Microsoft 365, Apple & more. EU-hosted.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceTransforms macOS calendar management into a conversational experience using natural language, allowing users to create, manage, and update calendar events seamlessly through an MCP-compatible client.327MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage Google Calendar through natural language interactions with features like creating, updating, and deleting events, searching calendars, and supporting natural language date/time inputs.272MIT
- FlicenseNot gradedqualityFmaintenanceEnables programmatic management of Google Calendar events through natural language interactions, supporting creation, reading, updating, and deletion of events with features for recurring events, attendees, and reminders.2
- AlicenseNot gradedqualityDmaintenanceEnables managing Google Calendar events including creating, listing, updating, and deleting events through natural language.17MIT
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/SarjuThakkar/skylight-mcp-pebble'
If you have feedback or need assistance with the MCP directory API, please join our Discord server