Cómo conecté LiftCoach con los asistentes de IA
ContenidoContents
Llevo un tiempo trabajando en LiftCoach, mi app de gimnasio para iPhone y Apple Watch. Ahora mismo está en TestFlight y la uso a diario para apuntar entrenos, rutinas y algo de nutrición. Hace unas semanas me propuse algo que me apetecía mucho: que cualquier asistente de IA compatible pudiera leer mis datos reales de entrenamiento y ayudarme a planificar, sin apaños y con un inicio de sesión de verdad.
Lo he resuelto con un conector MCP (Model Context Protocol). Os cuento cómo lo he montado, por fases, y alguna cosa que he aprendido por el camino.
De dónde partía
LiftCoach se sincroniza con una API propia escrita en Python con SQLite. Todo vive en mi servidor, aquí en España, detrás de Cloudflare y Apache. Nada de nubes de terceros para los datos.
Mi bot entrenador ya usaba un conector MCP local, por stdio, con un token fijo. Funcionaba, pero era una solución “de casa”: solo servía en mi máquina y dependía de un secreto estático. Para abrirlo a otros asistentes, y algún día a otros usuarios, necesitaba algo más serio.
Fase 1: endurecer la API sin tocar la app
Lo primero fue revisar la API. Me puse una regla: nada de esto podía obligarme a sacar una versión nueva de la app.
- Tokens guardados como hash SHA-256. Si alguien accediera a la base de datos, no encontraría tokens utilizables.
- Claves foráneas con borrado en cascada. Si se elimina una cuenta, se va todo lo que cuelga de ella, sin datos huérfanos.
- Endpoints para exportar y borrar la cuenta. Es lo que pide el RGPD y, sinceramente, es lo que me gustaría encontrar en cualquier app que use.
- Fuera el CORS comodín. Ese
*que uno pone “para probar” y luego se queda ahí para siempre.
Son cambios poco vistosos, pero son la base sobre la que se apoya todo lo demás.
Fase 2: un servidor MCP aparte
En vez de meter MCP dentro de la API, monté un servicio separado con el SDK oficial, en modo Streamable HTTP sin estado. Está publicado en https://sergiocomeron.com/liftcoach-mcp y expone diez herramientas:
- Lectura: atleta, entrenamientos, rutinas, ejercicios, nutrición, planes de comida y entrenamientos de Apple Health.
- Escritura: crear rutinas y crear planes de comida.
Lo que crea el asistente no se aplica directamente: llega a la bandeja de entrada de la app y soy yo quien decide si lo acepto. Me parece importante que la IA proponga y la persona decida, sobre todo con algo tan personal como el entrenamiento o la dieta.
Hacerlo sin estado simplifica mucho: cada petición trae todo lo que necesita, así que no tengo que gestionar sesiones en el servidor MCP.
Fase 3: OAuth 2.1 hecho en casa
Aquí estuvo el grueso del trabajo. Para que un asistente remoto acceda a tus datos, la especificación de MCP pide OAuth 2.1. Valoré usar un servicio como WorkOS, pero al final lo construí yo con Authlib. Quería entender cada pieza y mantener los datos y la autenticación en mi propio servidor.
Lo que incluye:
- PKCE con S256, obligatorio.
- Registro dinámico de clientes y soporte para Client ID Metadata Documents, para que un asistente pueda darse de alta solo, sin que yo tenga que crear credenciales a mano.
- Metadatos en
/.well-known, para que el cliente descubra dónde autorizar y dónde pedir tokens. - Access tokens JWT firmados con ES256, de 15 minutos de vida y con la audiencia del servidor MCP, de modo que no valen para otra cosa.
- Refresh tokens rotatorios con detección de reutilización: si alguien intenta usar uno ya gastado, se invalida la cadena.
- Revocación según el RFC 7009.
Para iniciar sesión uso Iniciar sesión con Apple en la web (con un Services ID). Tiene todo el sentido: los usuarios de LiftCoach ya tienen cuenta de Apple, y así no tengo que guardar contraseñas.
El flujo, simplificado, queda así:

El bug de la semana
No hay proyecto sin su bug tonto. El formulario de consentimiento, el último paso antes de entregar el código, daba un 404. Todo parecía bien configurado y no había manera. Al final era una ruta relativa en el formulario: como el servicio vive bajo un subdirectorio detrás de Apache, el navegador enviaba el POST a una URL que no existía. Cambiarla y listo. Horas de revisar la configuración del proxy para una barra.
Y un último tropiezo
Cuando ya lo daba por terminado, apareció otro. Autorizaba sin problema, pero al rato Grok Bot no conseguía renovar el token y mostraba un escueto «could not issue a new access token». La causa: los clientes MCP buscan los metadatos de OAuth en la raíz del dominio (/.well-known/oauth-protected-resource/liftcoach-mcp y /.well-known/oauth-authorization-server/liftcoach-api/oauth), no bajo el subdirectorio del servicio. Y Apache, con su regla que bloquea los ficheros que empiezan por punto, respondía con un 403. La solución fue añadir un ProxyPass para esas rutas hacia el servidor MCP y la API, recargar Apache y volver a conectar. Otra lección: con OAuth, el descubrimiento importa tanto como el propio flujo.
Probándolo de verdad
Lo he probado en Grok Bot y en Cursor. La experiencia es justo la que buscaba: añades el conector, te redirige a Apple, autorizas, y a partir de ahí el asistente lee tus datos reales. Le puedes preguntar cómo vas con el press de banca o pedirle que te prepare una rutina nueva, y la propuesta aparece en la bandeja de la app.
El conector antiguo por stdio sigue funcionando. Mi bot entrenador lo usa a diario y no quería cortar eso mientras el nuevo se asienta.
La migración
Y ese momento ya ha llegado. Rober, mi bot entrenador en Grok Bot, ya usa el nuevo conector MCP con OAuth. Antes de dar el paso le pedí que comparara los datos con los del conector antiguo, y coinciden al 100 %. Aun así, dejaré el conector antiguo unos días como respaldo antes de retirarlo definitivamente.
Privacidad y lo que viene
He publicado la web de la app, con la política de privacidad y los términos, en sergiocomeron.com/liftcoach. En resumen: el responsable del tratamiento soy yo como persona física, la app es para mayores de 16 años, no lleva SDKs de terceros, el servidor tiene el disco cifrado con FileVault y los logs se rotan.
También tengo preparada la solicitud para publicar el conector en los marketplaces de plugins de Grok Bot y Cursor. La enviaré cuando LiftCoach salga en la App Store; no tiene sentido ofrecer un conector para una app que todavía no se puede descargar.
Lo que me llevo
Venir del mundo del e-learning, de Moodle y PHP, ayuda bastante: allí también se trabaja con integraciones, estándares y datos personales que hay que cuidar. Pero montar un servidor OAuth completo desde cero me ha obligado a leer las RFC con calma y a entender por qué existe cada pieza.
Lo que más me gusta del resultado es que la app no ha tenido que cambiar. La API es más segura, el conector MCP es independiente y la autenticación es estándar. Si tenéis una app con API propia y os estáis planteando abrirla a asistentes de IA, MCP con OAuth bien hecho es un camino muy razonable.