@opsnow-mcp/opsnow-mcp-prototype-capture
v1.7.8
Published
MCP server for capturing prototype pages and extracting DOM structure
Readme
Prototype Capture MCP Server
프로토타입 페이지를 캡처하고 DOM 구조를 추출하는 MCP 서버입니다.
도구
captureWithDOM
페이지를 섹션별로 캡처하고 각 이미지에 해당하는 DOM 구조를 반환합니다.
파라미터
| 파라미터 | 타입 | 필수 | 설명 | |---------|------|------|------| | webflowUrl | string | O | 프로토타입 URL | | componentPath | string | O | 컴포넌트 생성 경로 (예: /src/components/dashboard) | | targetPath | string | X | 캡처할 경로 (예: "/dashboard") | | maxDepth | number | X | DOM 트리 최대 깊이 (기본값: 3) | | loginCredentials | object | X | 로그인 인증 정보 (username, password, mfaCode) | | waitTimeout | number | X | 페이지 로딩 대기 시간 (기본값: 60000ms) | | waitForSelectors | array | X | 로딩 완료 확인할 CSS 선택자 목록 | | debugLoading | boolean | X | 로딩 과정 디버그 메시지 표시 (기본값: false) |
refreshAllCaptures
프로젝트의 모든 컴포넌트 이미지를 최신화합니다. 자동으로 images/ 폴더가 있는 컴포넌트를 찾아 재캡처합니다.
파라미터
| 파라미터 | 타입 | 필수 | 설명 | |---------|------|------|------| | webflowUrl | string | O | 프로토타입 URL | | componentsPath | string | O | 컴포넌트들이 있는 최상위 디렉토리 (예: /src/components) | | maxDepth | number | X | DOM 트리 최대 깊이 (기본값: 3) |
동작 방식
componentsPath하위의 모든 디렉토리 스캔images/폴더가 있는 컴포넌트 자동 감지- 디렉토리 이름으로 라우트 추론 (예:
dashboard→/dashboard) - 각 컴포넌트를 순회하며 이미지 재캡처
주요 기능
🔐 인증 처리
- 로그인 자동화: 자격 증명 자동 입력
- MFA/OTP 지원: 2단계 인증 코드 처리
- 세션 재사용: 쿠키 저장 및 재사용으로 반복 로그인 방지
⏳ 고급 로딩 대기
- 프레임워크 감지: React, Vue, Angular, Next.js 자동 감지
- 동적 콘텐츠: AJAX/Fetch 요청 완료 대기
- 로딩 인디케이터: 스피너, 스켈레톤 UI 감지
- 리소스 로딩: 이미지, 폰트 완전 로딩 대기
- 콘텐츠 안정화: DOM 변경이 멈출 때까지 대기
동작 과정
1단계: 브라우저 실행 및 페이지 로드
Playwright Chromium 브라우저 실행
↓
뷰포트 설정 (1920x1080, 2x 스케일)
↓
대상 URL로 이동
↓
고급 로딩 대기 (프레임워크, AJAX, 리소스 등)
↓
네트워크 안정화 및 콘텐츠 안정화 대기2단계: 섹션 감지
페이지에서 시맨틱 HTML 태그를 찾아 섹션을 식별합니다.
// 감지 대상 태그
'header, nav, main, section, article, aside, footer'각 섹션에 대해:
- XPath 생성
- 위치/크기 정보 수집
- DOM 트리 구축
3단계: DOM 트리 구축
각 섹션의 DOM 구조를 간결하게 추출합니다.
섹션 요소
↓
자식 요소 순회 (깊이 제한: maxDepth)
↓
각 요소에서 추출:
- tag: 태그명
- id: ID (있는 경우)
- class: 클래스명 (최대 2개)
- component: 컴포넌트 타입 (감지된 경우)
- children: 자식 요소 (최대 5개, 초과 시 more 필드로 표시)4단계: 컴포넌트 타입 감지
DOM 요소를 분석하여 UI 컴포넌트 타입을 자동 감지합니다.
| 컴포넌트 | 감지 조건 |
|---------|----------|
| data-grid | table 태그, .grid, .table 클래스 |
| card | .card 클래스 |
| chart | .chart 클래스, canvas/svg 포함 |
| form | form 태그, input/select/textarea 3개 이상 |
| button | button 태그, .button 클래스 |
| nav | nav 태그 |
| sidebar | aside 태그, .sidebar 클래스 |
| tabs | .tab 클래스 |
5단계: 스크린샷 캡처
각 섹션을 개별 JPEG 이미지로 저장합니다.
섹션별 좌표로 영역 선택
↓
page.screenshot() with clip 호출
↓
JPEG 형식, quality: 85
↓
파일명: {componentName}-header.jpg, {componentName}-main.jpg, ...
(예: dashboard-header.jpg, dashboard-main.jpg)파일명 규칙:
- 일반 섹션:
{componentName}-{section}.jpg - 분할된 섹션 (3000px 초과):
{componentName}-{section}-{chunkNumber}.jpg
6단계: 결과 반환
JSON 형식으로 결과를 반환합니다.
반환 형식
{
"url": "https://example.webflow.io/dashboard",
"title": "Dashboard - Example",
"outputDir": "/path/to/project/src/components/dashboard/images",
"images": [
{
"file": "dashboard-header.jpg",
"path": "/full/path/to/dashboard-header.jpg",
"section": "header",
"dom": {
"tag": "header",
"class": "site-header",
"children": [
{
"tag": "nav",
"component": "nav",
"children": [
{ "tag": "a", "class": "logo" },
{ "tag": "ul", "class": "nav-links" }
]
}
]
}
},
{
"file": "dashboard-main.jpg",
"path": "/full/path/to/dashboard-main.jpg",
"section": "main",
"dom": {
"tag": "main",
"id": "content",
"children": [
{
"tag": "section",
"class": "card-grid",
"component": "card",
"children": [
{ "tag": "div", "class": "card" },
{ "tag": "div", "class": "card" },
{ "tag": "div", "class": "card" }
],
"more": 2
},
{
"tag": "div",
"class": "chart-container",
"component": "chart"
}
]
}
},
{
"file": "dashboard-footer.jpg",
"path": "/full/path/to/dashboard-footer.jpg",
"section": "footer",
"dom": {
"tag": "footer",
"children": [
{ "tag": "div", "class": "footer-links" },
{ "tag": "p", "class": "copyright" }
]
}
}
]
}DOM 구조 필드 설명
| 필드 | 타입 | 설명 |
|------|------|------|
| tag | string | HTML 태그명 |
| id | string | 요소 ID (있는 경우만) |
| class | string | 클래스명 (최대 2개, 공백 구분) |
| component | string | 감지된 컴포넌트 타입 |
| children | array | 자식 요소 배열 (최대 5개) |
| more | number | 생략된 자식 요소 수 |
사용 예시
메인 프로젝트에서 사용 (권장)
컴포넌트를 생성하면서 동시에 이미지 캡처:
프로젝트에서 /src/components/dashboard에 대시보드 컴포넌트를 만들어줘.
이미지는 captureWithDOM으로 캡처해서 같이 넣어줘.
- componentPath: {프로젝트절대경로}/src/components/dashboard
- targetPath: /dashboardClaude가 자동으로:
/src/components/dashboard/디렉토리 생성- 컴포넌트 파일 생성
/src/components/dashboard/images/에 스크린샷 저장
직접 호출
captureWithDOM({
webflowUrl: "https://example.webflow.io",
componentPath: "/Users/username/project/src/components/dashboard",
targetPath: "/dashboard"
})로그인이 필요한 페이지 캡처
로그인이 필요한 페이지를 캡처할 때는 loginCredentials를 전달하면 자동으로 로그인을 시도합니다:
captureWithDOM({
webflowUrl: "https://example.webflow.io",
componentPath: "/Users/username/project/src/components/dashboard",
targetPath: "/dashboard",
loginCredentials: {
username: "your-username",
password: "your-password"
}
})메인 프로젝트에서 사용:
로그인이 필요한 대시보드 페이지를 캡처해줘.
- 아이디: [email protected]
- 비밀번호: mypassword123동작 방식:
- 페이지 접속 후 로그인 폼 자동 감지
- username/email 필드와 password 필드에 자동 입력
- 로그인 버튼 클릭 또는 Enter 키 입력
- 로그인 완료 후 대상 페이지로 이동
- 페이지 캡처 및 DOM 구조 추출
DOM 깊이 조절
// 더 상세한 DOM 구조
captureWithDOM({
componentPath: "/path/to/component",
targetPath: "/dashboard",
maxDepth: 5
})
// 간략한 DOM 구조
captureWithDOM({
componentPath: "/path/to/component",
targetPath: "/dashboard",
maxDepth: 2
})전체 이미지 갱신
프로젝트의 모든 컴포넌트 이미지를 한 번에 최신화:
refreshAllCaptures({
webflowUrl: "https://example.webflow.io",
componentsPath: "/Users/username/project/src/components"
})실행 결과:
/src/components/ 스캔
├── dashboard/images/ ✓ → /dashboard 재캡처
├── settings/images/ ✓ → /settings 재캡처
├── profile/images/ ✓ → /profile 재캡처
└── common/ ✗ images 없음, 스킵메인 프로젝트에서 사용:
모든 컴포넌트 이미지를 최신화해줘
- refreshAllCaptures 사용
- componentsPath: {프로젝트절대경로}/src/components설정
.mcp.json 설정
{
"mcpServers": {
"opsnow-mcp-prototype-capture": {
"command": "node",
"args": [
"/path/to/mcp-servers/opsnow-mcp-prototype-capture/index.js"
],
"env": {
"WEBFLOW_URL": "https://example.webflow.io"
}
}
}
}환경변수 설명:
WEBFLOW_URL: Webflow 프로토타입 URL (필수)COMPONENT_PATH: 기본 컴포넌트 경로 (선택, 파라미터로 전달 권장)
출력 파일 구조
{componentPath}/images/
├── dashboard-header.jpg
├── dashboard-nav.jpg
├── dashboard-main.jpg
├── dashboard-main-1.jpg (분할된 경우)
├── dashboard-main-2.jpg (분할된 경우)
├── dashboard-aside.jpg
└── dashboard-footer.jpg예시: componentPath: /src/components/dashboard
/src/components/dashboard/
├── index.tsx
├── Dashboard.tsx
└── images/
├── dashboard-header.jpg
├── dashboard-main.jpg
└── dashboard-footer.jpg설계 원칙
- 컨텍스트 최소화 - 마크다운 설명 없이 JSON만 반환
- 구조화된 데이터 - AI가 파싱하기 쉬운 형식
- 이미지-DOM 매핑 - 각 이미지가 어떤 DOM 구조인지 명확
- 컴포넌트 감지 - UI 컴포넌트 타입 자동 식별
설치
팀원용 설치 가이드 (권장)
npm registry에 배포된 패키지를 사용하면 저장소 클론 없이 바로 사용할 수 있습니다.
- Claude Desktop 설정
~/Library/Application Support/Claude/claude_desktop_config.json 파일을 열어 다음 설정을 추가합니다:
{
"mcpServers": {
"opsnow-mcp-prototype-capture": {
"command": "npx",
"args": [
"-y",
"@opsnow-mcp/opsnow-mcp-prototype-capture"
],
"env": {
"WEBFLOW_URL": "https://your-webflow-url.webflow.io"
}
}
}
}설정 수정사항:
WEBFLOW_URL: 팀에서 사용하는 Webflow URL로 변경
- Claude Desktop 재시작
설정을 저장한 후 Claude Desktop을 완전히 종료하고 재시작합니다.
- 설치 확인
Claude Desktop에서 다음과 같이 테스트:
captureWithDOM으로 프로토타입 캡처해줘참고:
npx가 자동으로 패키지를 다운로드하고 실행합니다- 처음 실행 시 Playwright Chromium이 자동으로 설치됩니다
- 패키지 업데이트 시 자동으로 최신 버전을 사용합니다
로컬 개발용 설치
# 저장소 클론
git clone https://github.com/opsnow-common/opsnow-mcp-prototype-capture.git
cd opsnow-mcp-prototype-capture
# 의존성 설치
npm install
npx playwright install chromium
# 로컬에서 실행
npm startnpm 배포 가이드
Private npm Registry에 배포
- npm registry 설정 확인
# 현재 registry 확인
npm config get registry
# OpsNow private registry로 변경 (필요한 경우)
npm config set registry https://your-npm-registry.com- 로그인
npm login- 배포
# 패키지 배포
npm publish
# 특정 태그로 배포
npm publish --tag beta- 버전 업데이트 후 재배포
# 패치 버전 올리기 (2.0.0 -> 2.0.1)
npm version patch
# 마이너 버전 올리기 (2.0.0 -> 2.1.0)
npm version minor
# 메이저 버전 올리기 (2.0.0 -> 3.0.0)
npm version major
# 배포
npm publish배포 후 팀원 사용
팀원들은 별도 설치 없이 Claude Desktop 설정만 추가하면 바로 사용 가능합니다:
{
"mcpServers": {
"opsnow-mcp-prototype-capture": {
"command": "npx",
"args": ["-y", "@opsnow-mcp/opsnow-mcp-prototype-capture"],
"env": {
"WEBFLOW_URL": "https://your-webflow-url.webflow.io"
}
}
}
}라이선스
MIT
