pilates_mcp
pilates_mcp
pilates_mcp는 필라테스 센터 홍보 포스터를 위한 로컬 우선(local-first) MCP 서버입니다. 편집 가능한 HTML/CSS 포스터 소스를 생성하고, 로컬 아카이브에 저장하며, 과거 포스터를 검색하고 재사용하며, 디자인 피드백을 기록하고, 헤드리스 Chromium으로 PNG/PDF 아티팩트를 렌더링할 수 있습니다.
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로 구성됩니다.
프로덕션 컨테이너는 공식 Playwright 이미지를 사용하므로 PNG/PDF 렌더링에 필요한 Chromium 런타임 종속성을 사용할 수 있습니다. Railway는 npm run start:railway를 시작하며, 이는 다음을 노출합니다:
GET /health: 배포 상태 확인GET /tools: 배포 점검을 위한 MCP 도구 요약GET /schedule: 경량 Excel 스타일 Schedule Workspace
stdio MCP 서버는 명령으로 연결하는 MCP 클라이언트를 위해 npm run start를 통해 계속 사용할 수 있습니다. stdio MCP는 HTTP 포트를 노출하지 않으므로 Railway 상태 확인 프로세스는 의도적으로 분리되어 있습니다.
Railway에서 영구적인 로컬 우선 아카이브 저장을 위해 /data에 Railway 볼륨을 마운트하거나 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(가격 콘텐츠가 있는 경우)
서버는 누락된 이벤트 이름, VAT 정책 또는 프로그램 구분을 추측하는 대신 valid: false, missing 및 한국어 questions를 반환합니다.
programSeparation과 tableStyle은 별개의 결정 사항입니다. 예를 들어, 그룹/개인 상품은 tableStyle: "split"과 함께 programSeparation: "table"을 사용하여 별도의 GROUP/PRIVATE 테이블 블록을 렌더링할 수 있습니다. tablePreference는 사용자 의도를 나타내며, layout은 최종 렌더러 선택입니다.
센터 기본값은 반복되는 질문을 줄일 수 있습니다:
{
"posterDefaults": {
"programSeparation": "table",
"tablePreference": "required",
"tableStyle": "split",
"vatPolicy": "excluded"
}
}우선순위는 다음과 같습니다: 현재 요청 및 PosterBrief, 그 다음 센터 프로필 기본값, 그 다음 누락된 값만 사용자에게 묻는 검증 응답입니다. VAT는 절대 추론되지 않습니다.
예시
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
}피드백
피드백은 하드코딩되지 않고 JSON 파일에 저장됩니다. create_poster는 활성 글로벌 및 레이아웃 범위 피드백을 검색하여 결과에 appliedFeedback으로 포함합니다.
예시:
{
"scope": "table",
"text": "이벤트가는 정상가보다 확실히 강조."
}렌더링
render_poster는 JavaScript가 비활성화된 Playwright Chromium을 사용합니다. 지원되는 크기:
instagram-portrait: 1080 x 1350instagram-square: 1080 x 1080story: 1080 x 1920a4-portrait: A4 세로
HTML/CSS가 진실의 원천(source of truth)입니다. PNG/PDF는 선택적 렌더링 아티팩트입니다.
Schedule Workspace
Phase 2는 필라테스 그룹/개인 시간표를 위한 로컬 우선 Schedule Workspace를 추가합니다. 이는 CRM이 아닙니다. 개인 일정에는 그리드 표시 및 운영 배치를 위해서만 displayName이 포함될 수 있습니다.
핵심 모델:
ScheduleSettings: 주 표시, 개점/폐점 시간, 기본 슬롯 분, 휴일 옵션, 로케일, 국가 코드ScheduleTemplate: 명시적 저장 주간 그룹/개인 템플릿ScheduleSlot: Excel 셀과 분리된 중립 도메인 슬롯ScheduleTemplateMapping: XLSX 워크시트/헤더/시간/요일 열 매핑CenterClosure: 공휴일과 분리된 센터별 휴무일
set_schedule_slot은 메모리 내 더티(dirty) 작업 공간을 변경합니다. save_schedule이 호출되기 전까지는 영구 저장되지 않습니다. export_schedule은 XLSX를 작성하고 기존 XLSX를 교체하기 전에 백업합니다.
기존 XLSX 파일은 inspect_schedule_file과 import_schedule_file로 처리됩니다. 임포터는 워크시트 이름, 사용 범위, 요일 열, 시간 열, 열 너비, 행 높이 및 가능한 병합을 캡처합니다. 수식은 실행되지 않습니다.
휴일 처리는 공급자(provider) 기반입니다. Phase 2에는 기본 KR 휴일 픽스처를 제공하는 로컬 공급자가 포함되며, 도메인 모델을 변경하지 않고 나중에 외부 공급자로 교체할 수 있습니다. 센터 휴무일이 공휴일보다 우선하지만, 점유된 슬롯은 조용히 삭제되지 않으며 경고가 반환됩니다.
Railway는 /schedule에서 고정 헤더, 직접 셀 편집, 삭제/백스페이스 및 표시 가능한 저장 상태를 갖춘 경량 Excel 스타일 작업 공간을 제공합니다. 실제 일정 작업의 소스는 MCP로 유지됩니다.
Schedule 예시
시나리오 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를 비활성화합니다.
Phase 1은 회원 관리, 예약, 결제, SMS, Instagram 게시, StudioMate 통합, 외부 디자인 스크래핑, 이미지 생성 AI, 클라우드 DB 요구 사항 및 SaaS 인증을 제외합니다.
Phase 2는 개인 관련 일정 표시 데이터로 displayName만 허용합니다. 전화, 이메일, 주소, 생년월일, 성별, 건강 상태, 병력, 결제, 회원권, 상담, 출석 프로필 또는 마케팅 동의 필드를 생성하지 않습니다. 이름은 프로파일링, 분석, 포스터 피드백, 마케팅 또는 추천에 사용되지 않습니다.
Phase 2는 여전히 StudioMate 통합, StudioMate 스크래핑, Chrome 확장 프로그램 자동화, 회원 CRM, 연락처 관리, 결제 관리, 출석 분석, 회원 선호도 프로파일링, 자동 예약 확인, SMS, KakaoTalk, Instagram 게시, 급여, 정산 및 복잡한 ERP 기능을 제외합니다.
확장 지점
서비스/리포지토리 분리는 향후 의미론적 검색 또는 다른 인덱스를 위한 여지를 남깁니다. 외부 디자인 참조는 다음과 같은 공급자 인터페이스 뒤에 나중에 추가할 수 있습니다:
interface DesignReferenceProvider {
search(query: string): Promise<DesignReference[]>;
}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