pilates_mcp
pilates_mcp
pilates_mcp — это локальный MCP-сервер для рекламных постеров пилатес-центра. Он создаёт редактируемые HTML/CSS-исходники постеров, хранит их в локальном архиве, ищет и повторно использует прошлые постеры, записывает отзывы о дизайне и может рендерить PNG/PDF-артефакты с помощью headless Chromium.
На этапе 1 (Phase 1) сервер намеренно не хранит имена участников, номера телефонов, расписания, данные о здоровье, платёжные данные и прочую личную информацию участников.
Структура проекта
На момент реализации репозиторий был пуст, поэтому сервер реализован как TypeScript + Node.js MCP-сервер.
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
Установка
npm install
npx playwright install chromiumРазработка
npm run build
npm test
npm run devPILATES_MCP_DATA_DIR может указывать на другую локальную директорию для архива. Если переменная не задана, сервер использует ./data.
Деплой на Railway
Деплой на Railway настраивается с помощью railway.json и Dockerfile.
В production-контейнере используется официальный образ Playwright, поэтому зависимости Chromium доступны для рендеринга PNG/PDF. Railway запускает npm run start:railway, который предоставляет:
GET /health— проверка работоспособности деплояGET /tools— сводка MCP-инструментов для проверки деплояGET /schedule— лёгкое рабочее пространство в стиле Excel для расписания
MCP-сервер stdio остаётся доступным через npm run start для MCP-клиентов, подключающихся по команде. Процесс проверки работоспособности на Railway намеренно отдельный, потому что stdio MCP не предоставляет HTTP-порт.
Для постоянного локального хранения архива на Railway смонтируйте том Railway в /data или задайте PILATES_MCP_DATA_DIR как другой постоянный путь.
Подключение MCP-клиента
Используйте собранный сервер как stdio MCP-команду:
{
"mcpServers": {
"pilates_mcp": {
"command": "node",
"args": ["G:/pilates_mcp/dist/src/server.js"],
"env": {
"PILATES_MCP_DATA_DIR": "G:/pilates_mcp/data"
}
}
}
}Инструменты
Инструменты для постеров:
get_center_profileupdate_center_profilesearch_postersget_postercreate_posterupdate_posterreuse_poster_templateimport_posterrender_posteradd_design_feedbackget_design_feedbackrecommend_poster_style
Инструменты для расписания:
get_schedule_settingsupdate_schedule_settingsinspect_schedule_fileimport_schedule_filecreate_schedule_templateget_schedulegenerate_weekly_scheduleset_schedule_slotclear_schedule_slotfind_available_slotsvalidate_scheduleadd_center_closureremove_center_closureget_center_closuressave_scheduleexport_schedulecreate_schedule_poster
Процесс создания постера
create_poster читает профиль центра, применяет значения по умолчанию из профиля, проверяет PosterBrief, собирает релевантные отзывы, определяет макет и тему, рендерит статический HTML/CSS, записывает метаданные/контент/исходные файлы и при необходимости рендерит PNG/PDF.
Требуемый порядок:
user request
-> center profile defaults
-> PosterBrief
-> validation
-> ask only missing questions
-> past posters and feedback
-> HTML/CSS
-> optional render
-> archive saveОбязательные решения по брифу постера проверяются до генерации:
eventNameprogramSeparationtablePreferencetableStyle, если таблица требуется или указанаvatPolicy, если в контенте есть цены
Сервер возвращает valid: false, missing и вопросы на корейском (questions) вместо того, чтобы угадывать отсутствующие название события, политику НДС или разделение программ.
programSeparation и tableStyle — это отдельные решения. Например, для групповых/индивидуальных продуктов можно использовать programSeparation: "table" с tableStyle: "split", чтобы отображать отдельные блоки таблиц GROUP/PRIVATE. tablePreference отражает намерение пользователя; layout — это итоговый выбор рендерера.
Значения по умолчанию из профиля центра позволяют сократить повторяющиеся вопросы:
{
"posterDefaults": {
"programSeparation": "table",
"tablePreference": "required",
"tableStyle": "split",
"vatPolicy": "excluded"
}
}Приоритет такой: текущий запрос и PosterBrief, затем значения по умолчанию из профиля центра, затем проверочный ответ с запросом у пользователя только недостающих значений. НДС никогда не выводится автоматически.
Примеры
Создание постера с прайс-таблицей за август
{
"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" }
}Повторное использование шаблона постера за сентябрь прошлого года
{
"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
}
}
}Рекомендация стиля на основе записей за последний год
{
"purpose": "event",
"month": 9,
"recentMonths": 12
}Отзывы
Отзывы хранятся в JSON-файлах, а не зашиты в код. create_poster получает активные отзывы глобального уровня и уровня макета и включает их в результат как appliedFeedback.
Пример:
{
"scope": "table",
"text": "이벤트가는 정상가보다 확실히 강조."
}Рендеринг
render_poster использует Playwright Chromium с отключённым JavaScript. Поддерживаемые размеры:
instagram-portrait: 1080 x 1350instagram-square: 1080 x 1080story: 1080 x 1920a4-portrait: A4, книжная ориентация
HTML/CSS — это источник истины. PNG/PDF — опциональные артефакты.
Рабочее пространство расписания
На этапе 2 (Phase 2) добавляется локальное рабочее пространство расписания для групповых/индивидуальных занятий пилатесом. Это не CRM. В частных расписаниях может содержаться только displayName — для отображения в сетке и оперативного размещения.
Основная модель:
ScheduleSettings: неделя отображения, время открытия/закрытия, длительность слота по умолчанию, опция выходных, локаль, код страныScheduleTemplate: явное сохранение еженедельного шаблона для групповых/индивидуальных занятийScheduleSlot: нейтральный доменный слот, отдельный от ячеек ExcelScheduleTemplateMapping: сопоставление XLSX-листа/заголовков/времени/дней/колонокCenterClosure: даты закрытия конкретного центра, отдельные от государственных праздников
set_schedule_slot изменяет слот в памяти (dirty-состояние). Изменения не сохраняются, пока не вызван save_schedule. export_schedule записывает XLSX и перед заменой делает резервную копию существующего файла.
Существующие XLSX-файлы обрабатываются через inspect_schedule_file и import_schedule_file. Импортёр захватывает имя листа, используемый диапазон, колонки дней, колонку времени, ширины колонок, высоты строк и объединённые ячейки там, где они есть. Формулы не выполняются.
Обработка праздников основана на провайдере. На этапе 2 (Phase 2) встроен локальный провайдер с базовыми праздниками Южной Кореи; позже его можно заменить внешним провайдером без изменения доменной модели. Закрытия центров имеют приоритет над государственными праздниками, но занятые слоты не удаляются молча — возвращаются предупреждения.
Railway предоставляет лёгкое рабочее пространство в стиле Excel по адресу /schedule с закреплёнными шапками, прямым редактированием ячеек, удалением клавишами Delete/Backspace и видимым состоянием сохранения. MCP остаётся источником реальных операций с расписанием.
Примеры работы с расписанием
Сценарий A: создание нового группового расписания, когда файла ещё нет:
{
"scheduleType": "group",
"settings": {
"weekDisplay": "mon-sat",
"openingTime": "09:00",
"closingTime": "21:00",
"defaultSlotMinutes": 60,
"autoHolidayMarking": true,
"locale": "ko-KR",
"countryCode": "KR"
}
}Сценарий B: импорт существующего Excel-файла и генерация расписания на следующую неделю:
{ "filePath": "fixtures/group_schedule.xlsx", "scheduleType": "group" }{
"scheduleType": "group",
"weekStart": "2026-10-05",
"applyHolidays": true,
"applyCenterClosures": true
}Сценарий C: операция с индивидуальным расписанием:
{
"scheduleType": "private",
"dayOfWeek": "monday",
"startTime": "19:00",
"displayName": "김OO"
}Сценарий D: постер группового расписания:
{
"scheduleType": "group",
"weekStart": "2026-10-05",
"title": "9월 그룹레슨 시간표",
"render": { "png": true, "pdf": true, "size": "instagram-portrait" }
}Безопасность и конфиденциальность
В архиве используются сгенерированные ID постеров, и ID проверяются перед доступом к файлу. Импорт проверяется на относительные пути, чтобы заблокировать обход через ../ и выход за пределы корня. Сгенерированный HTML постеров статичен, пользовательский текст экранируется для HTML, а удалённые скрипты не являются частью шаблона. При рендеринге JavaScript отключён.
На этапе 1 (Phase 1) исключены: управление участниками, бронирование, платежи, SMS, публикация в Instagram, интеграция со StudioMate, внешний скрейпинг дизайнов, генерация изображений через ИИ, облачные базы данных и SaaS-аутентификация.
На этапе 2 (Phase 2) в данных расписания, связанных с людьми, допускается только displayName. Не создаются поля для телефона, email, даты рождения, пола, состояния здоровья, истории болезней, платежей, членства, консультаций, посещаемости, маркетинговых предпочтений и согласий. Имена не используются для профилирования, аналитики, отзывов о постерах, маркетинга или рекомендаций.
На этапе 2 (Phase 2) по-прежнему исключены: интеграция со StudioMate, скрейпинг StudioMate, автоматизация через расширения Chrome, CRM участников, управление контактами, управление платежами, анализ посещаемости, профилирование предпочтений участников, автоматическое подтверждение бронирований, SMS, KakaoTalk, публикация в Instagram, расчёт зарплат, расчёты и сложные ERP-функции.
Точки расширения
Разделение на сервис и репозиторий оставляет место для будущего семантического поиска или другого индекса. Внешние источники дизайнов можно добавить позже за интерфейсом провайдера, например:
interface DesignReferenceProvider {
search(query: string): Promise<DesignReference[]>;
}На этапе 1 (Phase 1) не реализованы скрейпинг и копирование внешних шаблонов.
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 Servers
- AlicenseAqualityDmaintenanceMCP server that turns articles, transcripts, and markdown into LinkedIn carousel PDFs, Instagram PNGs, and Threads PNGs. Content in, slides out. No web UI, no cloud service.51MIT
- AlicenseNot gradedqualityBmaintenanceLocal-first MCP server for research on AI-assisted browsing of a user-owned professional-network account (e.g., LinkedIn), providing read-focused tools such as profile, company, search, and feed reads.MIT
- AlicenseBqualityAmaintenanceLocal-first MCP server that transforms civil case PDFs into queryable cases with structural provenance, evidence IDs, and page-level verification for drafting and factual review.22Apache 2.0
- AlicenseNot gradedqualityBmaintenanceLocal-first personal productivity MCP server bundling email, calendar, messaging, search, and image generation tools with BYOK and no cloud dependency.50MIT
Related MCP Connectors
WordPress MCP server: publish posts, AI images, SEO and full site management, self-hosted
MCP server for Zooza — class scheduling, attendance, and booking for activity businesses.
Private-by-default, local-first memory/context/task orchestrator for MCP apps and agents.
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/sebit-provider/pilates_mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server