Skip to main content
Glama

pilates_mcp

pilates_mcp es un servidor MCP local-first para carteles promocionales de centros de Pilates. Crea fuentes de carteles HTML/CSS editables, las almacena en un archivo local, busca y reutiliza carteles anteriores, registra comentarios de diseño y puede generar artefactos PNG/PDF con Chromium sin interfaz gráfica.

La Fase 1 deliberadamente no almacena nombres de miembros, números de teléfono, horarios, datos de salud, datos de pago ni otra información personal de los miembros.

Estructura del Proyecto

Este repositorio estaba vacío en el momento de la implementación, por lo que el servidor está implementado como un servidor MCP de TypeScript + Node.js.

src/
  server.ts        MCP stdio JSON-RPC transport and tool dispatch
  service.ts       poster workflow orchestration
  repository.ts    local poster archive search/read/write
  renderer.ts      Playwright PNG/PDF renderer
  templates.ts     HTML/CSS template layer
  feedback.ts      design feedback storage
  profile.ts       center profile storage
  themes.ts        design token presets
  types.ts         domain types
data/
  posters/YYYY/<poster-id>/
    poster.html
    poster.css
    metadata.json
    content.json
    preview.png    optional
    poster.pdf     optional
    revisions/     update backups
  feedback/
    global.json
    table.json
    standard.json
    poster-<poster-id>.json
  config/
    center-profile.json
  schedules/
    settings.json
    center-closures.json
    group/
      template.json
      group_schedule.xlsx
      revisions/
    private/
      template.json
      private_schedule.xlsx
      revisions/

Related MCP server: Networking MCP

Instalación

npm install
npx playwright install chromium

Desarrollo

npm run build
npm test
npm run dev

PILATES_MCP_DATA_DIR puede apuntar el archivo a otro directorio de datos local. Si no se establece, el servidor usa ./data.

Despliegue en Railway

El despliegue en Railway está configurado con railway.json y Dockerfile.

El contenedor de producción usa la imagen oficial de Playwright para que las dependencias de runtime de Chromium estén disponibles para el renderizado PNG/PDF. Railway inicia npm run start:railway, que expone:

  • GET /health: comprobación de salud del despliegue

  • GET /tools: resumen de herramientas MCP para inspección del despliegue

  • GET /schedule: Workspace de Horarios ligero estilo Excel

El servidor MCP stdio sigue disponible mediante npm run start para clientes MCP que se conectan por comando. El proceso de salud de Railway es intencionalmente separado porque MCP stdio no expone un puerto HTTP.

Para almacenamiento persistente local-first en Railway, monta un volumen de Railway en /data o establece PILATES_MCP_DATA_DIR en otra ruta persistente.

Conexión del Cliente MCP

Usa el servidor compilado como comando MCP stdio:

{
  "mcpServers": {
    "pilates_mcp": {
      "command": "node",
      "args": ["G:/pilates_mcp/dist/src/server.js"],
      "env": {
        "PILATES_MCP_DATA_DIR": "G:/pilates_mcp/data"
      }
    }
  }
}

Herramientas

Herramientas de carteles:

  • get_center_profile

  • update_center_profile

  • search_posters

  • get_poster

  • create_poster

  • update_poster

  • reuse_poster_template

  • import_poster

  • render_poster

  • add_design_feedback

  • get_design_feedback

  • recommend_poster_style

Herramientas de horarios:

  • get_schedule_settings

  • update_schedule_settings

  • inspect_schedule_file

  • import_schedule_file

  • create_schedule_template

  • get_schedule

  • generate_weekly_schedule

  • set_schedule_slot

  • clear_schedule_slot

  • find_available_slots

  • validate_schedule

  • add_center_closure

  • remove_center_closure

  • get_center_closures

  • save_schedule

  • export_schedule

  • create_schedule_poster

Flujo de Creación de Carteles

create_poster lee el perfil del centro, aplica los valores predeterminados del centro, valida el PosterBrief, recopila comentarios relevantes, resuelve el diseño y el tema, renderiza HTML/CSS estático, escribe archivos de metadatos/contenido/fuente y opcionalmente renderiza PNG/PDF.

El orden requerido es:

user request
-> center profile defaults
-> PosterBrief
-> validation
-> ask only missing questions
-> past posters and feedback
-> HTML/CSS
-> optional render
-> archive save

Las decisiones obligatorias del brief del cartel se validan antes de la generación:

  • eventName

  • programSeparation

  • tablePreference

  • tableStyle cuando se requiere o se proporciona una tabla

  • vatPolicy cuando existe contenido de precios

El servidor devuelve valid: false, missing y questions en coreano en lugar de adivinar nombres de eventos, política de IVA o separación de programas que falten.

programSeparation y tableStyle son decisiones separadas. Por ejemplo, los productos grupales/privados pueden usar programSeparation: "table" con tableStyle: "split" para renderizar bloques de tabla GRUPAL/PRIVADA separados. tablePreference representa la intención del usuario; layout es la elección final del renderizador.

Los valores predeterminados del centro pueden reducir preguntas repetidas:

{
  "posterDefaults": {
    "programSeparation": "table",
    "tablePreference": "required",
    "tableStyle": "split",
    "vatPolicy": "excluded"
  }
}

La prioridad es: solicitud actual y PosterBrief, luego valores predeterminados del perfil del centro, y luego una respuesta de validación que pide al usuario solo los valores que faltan. El IVA nunca se infiere.

Ejemplos

8월 회원권 가격표 포스터 생성

{
  "title": "8월 회원권 이벤트",
  "purpose": "event",
  "brief": {
    "eventName": "8월 회원권 이벤트",
    "programCategories": ["private", "duet"],
    "programSeparation": "table",
    "tablePreference": "required",
    "tableStyle": "comparison",
    "vatPolicy": "excluded"
  },
  "content": {
    "subtitle": "이번 달 특별 혜택",
    "badge": "8월 EVENT",
    "table": {
      "columns": ["상품", "정상가", "이벤트가"],
      "rows": [
        ["1:1 개인레슨 10회", "800,000원", "650,000원"],
        ["듀엣레슨 10회", "500,000원", "390,000원"]
      ],
      "highlightColumn": 2
    },
    "footer": "선착순 마감"
  },
  "style": "premium",
  "render": { "png": true, "pdf": true, "size": "instagram-portrait" }
}

작년 9월 포스터 틀 재사용

{
  "sourcePosterId": "poster_20250901_ab12cd34",
  "title": "2026년 9월 신규회원 이벤트",
  "brief": {
    "eventName": "9월 신규회원 이벤트",
    "vatPolicy": "excluded"
  },
  "content": {
    "subtitle": "올해 가격으로 업데이트",
    "table": {
      "columns": ["상품", "정상가", "이벤트가"],
      "rows": [["1:1 개인레슨 10회", "820,000원", "670,000원"]],
      "highlightColumn": 2
    }
  }
}

최근 1년 기록 기반 스타일 추천

{
  "purpose": "event",
  "month": 9,
  "recentMonths": 12
}

Comentarios

Los comentarios se almacenan en archivos JSON, no están codificados. create_poster recupera comentarios activos globales y con ámbito de diseño y los incluye en el resultado como appliedFeedback.

Ejemplo:

{
  "scope": "table",
  "text": "이벤트가는 정상가보다 확실히 강조."
}

Renderizado

render_poster usa Playwright Chromium con JavaScript deshabilitado. Tamaños admitidos:

  • instagram-portrait: 1080 x 1350

  • instagram-square: 1080 x 1080

  • story: 1080 x 1920

  • a4-portrait: A4 vertical

HTML/CSS son la fuente de verdad. PNG/PDF son artefactos renderizados opcionales.

Workspace de Horarios

La Fase 2 añade un Workspace de Horarios local-first para horarios grupales/privados de Pilates. No es un CRM. Los horarios privados pueden contener displayName solo para visualización en cuadrícula y colocación operativa.

Modelo principal:

  • ScheduleSettings: visualización semanal, hora de apertura/cierre, minutos de franja predeterminados, opción de festivos, locale, código de país

  • ScheduleTemplate: plantilla semanal grupal/privada con guardado explícito

  • ScheduleSlot: franja de dominio neutral separada de las celdas de Excel

  • ScheduleTemplateMapping: mapeo de hoja de cálculo/encabezado/hora/columna de día de XLSX

  • CenterClosure: fechas cerradas específicas del centro, separadas de los festivos nacionales

set_schedule_slot cambia un workspace sucio en memoria. No se persiste hasta que se llama a save_schedule. export_schedule escribe XLSX y hace una copia de seguridad de un XLSX existente antes de reemplazarlo.

Los archivos XLSX existentes se gestionan con inspect_schedule_file e import_schedule_file. El importador captura el nombre de la hoja de cálculo, el rango usado, las columnas de día, la columna de hora, los anchos de columna, las alturas de fila y las celdas combinadas cuando están disponibles. Las fórmulas no se ejecutan.

El manejo de festivos se basa en proveedores. La Fase 2 incluye un proveedor local con datos básicos de festivos de KR y puede reemplazarse más adelante por un proveedor externo sin cambiar el modelo de dominio. Los cierres del centro tienen prioridad sobre los días festivos públicos, pero las franjas ocupadas no se eliminan silenciosamente; se devuelven advertencias.

Railway sirve un workspace ligero estilo Excel en /schedule con encabezados fijos, edición directa de celdas, eliminar/retroceso y estado de guardado visible. MCP sigue siendo la fuente de las operaciones reales de horarios.

Ejemplos de Horarios

Escenario A, crear un nuevo horario grupal cuando no existe ningún archivo:

{
  "scheduleType": "group",
  "settings": {
    "weekDisplay": "mon-sat",
    "openingTime": "09:00",
    "closingTime": "21:00",
    "defaultSlotMinutes": 60,
    "autoHolidayMarking": true,
    "locale": "ko-KR",
    "countryCode": "KR"
  }
}

Escenario B, importar un archivo Excel existente y generar la próxima semana:

{ "filePath": "fixtures/group_schedule.xlsx", "scheduleType": "group" }
{
  "scheduleType": "group",
  "weekStart": "2026-10-05",
  "applyHolidays": true,
  "applyCenterClosures": true
}

Escenario C, operación de horario privado:

{
  "scheduleType": "private",
  "dayOfWeek": "monday",
  "startTime": "19:00",
  "displayName": "김OO"
}

Escenario D, cartel de horario grupal:

{
  "scheduleType": "group",
  "weekStart": "2026-10-05",
  "title": "9월 그룹레슨 시간표",
  "render": { "png": true, "pdf": true, "size": "instagram-portrait" }
}

Seguridad y Privacidad

El archivo usa IDs de carteles generados y valida los IDs de carteles antes del acceso a archivos. Las importaciones relativas al archivo se comprueban para bloquear el recorrido ../ y el escape de la raíz. El HTML de carteles generado es estático, el texto del usuario está escapado en HTML y los scripts remotos no forman parte de la plantilla. El renderizado deshabilita JavaScript.

La Fase 1 excluye gestión de miembros, reservas, pagos, SMS, publicación en Instagram, integración con StudioMate, extracción de diseños externos, IA de generación de imágenes, requisitos de base de datos en la nube y autenticación SaaS.

La Fase 2 solo permite displayName como dato de visualización de horarios relacionado con personas. No crea campos para teléfono, correo electrónico, dirección, fecha de nacimiento, género, condición de salud, historial médico, pago, membresía, consulta, perfil de asistencia ni consentimiento de marketing. Los nombres no se usan para elaboración de perfiles, análisis, comentarios de carteles, marketing ni recomendaciones.

La Fase 2 sigue excluyendo integración con StudioMate, extracción de datos de StudioMate, automatización de extensiones de Chrome, CRM de miembros, gestión de contactos, gestión de pagos, análisis de asistencia, elaboración de perfiles de preferencias de miembros, confirmación automática de reservas, SMS, KakaoTalk, publicación en Instagram, nóminas, liquidaciones y funciones complejas de ERP.

Puntos de Extensión

La separación servicio/repositorio deja espacio para futuras búsquedas semánticas u otro índice. Las referencias de diseño externas pueden añadirse más adelante detrás de una interfaz de proveedor como:

interface DesignReferenceProvider {
  search(query: string): Promise<DesignReference[]>;
}

La Fase 1 no implementa extracción ni copia de plantillas externas.

Install Server
F
license - not found
B
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

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/sebit-provider/pilates_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server