Skip to main content
Glama

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 dev

PILATES_MCP_DATA_DIR은 아카이브를 다른 로컬 데이터 디렉터리로 지정할 수 있습니다. 설정하지 않으면 서버는 ./data를 사용합니다.

Railway 배포

Railway 배포는 railway.jsonDockerfile로 구성됩니다.

프로덕션 컨테이너는 공식 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_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

일정 도구:

  • 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

포스터 생성 흐름

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

필수 포스터 브리프 결정 사항은 생성 전에 검증됩니다:

  • eventName

  • programSeparation

  • tablePreference

  • tableStyle (테이블이 필요하거나 제공된 경우)

  • vatPolicy (가격 콘텐츠가 있는 경우)

서버는 누락된 이벤트 이름, VAT 정책 또는 프로그램 구분을 추측하는 대신 valid: false, missing 및 한국어 questions를 반환합니다.

programSeparationtableStyle은 별개의 결정 사항입니다. 예를 들어, 그룹/개인 상품은 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 1350

  • instagram-square: 1080 x 1080

  • story: 1080 x 1920

  • a4-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_fileimport_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은 외부 템플릿 스크래핑 또는 복사를 구현하지 않습니다.

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