# Palette MCP Server - 아키텍처 및 개발 방식
## 시스템 아키텍처
### 전체 구조
```
┌─────────────────────────────────────────────────────────────────┐
│ AI Client (Cursor) │
│ │ │
│ MCP Protocol │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Palette MCP Server │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │
│ │ │ FigmaService│ │DesignSystem │ │ CodeGenerator │ │ │
│ │ │ │ │ Service │ │ │ │ │
│ │ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │ │
│ └──────────┼────────────────┼──────────────────┼────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ Figma MCP │ │ GitHub │ │ Generated │ │
│ │ (Desktop) │ │ (ssm-web) │ │ Files │ │
│ └─────────────┘ └──────────────┘ └───────────────┘ │
│ or │
│ ┌─────────────┐ │
│ │ Figma REST │ │
│ │ API │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 프로젝트 구조
```
src/
├── index.ts # MCP 서버 진입점 (Local 모드)
├── server.ts # MCP 서버 핵심 로직 (Tools, Prompts, Resources 정의)
├── smithery.ts # Remote 모드 (Smithery.ai 배포용)
│
├── services/
│ ├── figma.ts # Figma 데이터 가져오기 (MCP 우선, REST API 폴백)
│ ├── design-system.ts # 디자인 시스템 컴포넌트 레지스트리 및 매핑
│ └── code-generator.ts # React/Vue 코드 생성 및 프리뷰 생성
│
├── sync/
│ ├── index.ts # 동기화 서비스 통합
│ ├── component-sync.ts # GitHub 기반 컴포넌트 동기화
│ ├── github-client.ts # GitHub API 클라이언트
│ ├── typescript-analyzer.ts # TypeScript AST 분석기
│ └── cache-manager.ts # 동기화 캐시 관리
│
└── utils/
├── figma-mcp-client.ts # Figma Desktop MCP 클라이언트
└── request-manager.ts # 요청 ID 및 파일 저장 관리
```
---
## 핵심 서비스
### 1. FigmaService (`services/figma.ts`)
Figma 데이터를 가져오는 서비스로, **MCP 우선 + REST API 폴백** 전략을 사용합니다.
#### 데이터 가져오기 전략
```
1. Figma Desktop MCP 서버 연결 시도 (localhost:3845)
├── 성공 → MCP 프로토콜로 데이터 가져오기
└── 실패 → REST API 폴백
2. Figma REST API 사용 (폴백)
└── FIGMA_ACCESS_TOKEN 필요
```
#### 주요 기능
| 메서드 | 설명 |
|--------|------|
| `getFigmaData(url, nodeId?)` | Figma 파일/노드 데이터 가져오기 |
| `analyzeFigmaFile(url)` | 파일 구조 분석 |
| `extractDesignTokens(file)` | 디자인 토큰 추출 |
### 2. DesignSystemService (`services/design-system.ts`)
디자인 시스템 컴포넌트 메타데이터를 관리합니다.
#### 컴포넌트 동기화
서버 시작 시 GitHub의 `ssm-web` 저장소에서 최신 컴포넌트 정보를 동기화합니다.
```
1. 서버 시작
2. ComponentSyncService 호출
3. GitHub API로 컴포넌트 파일 조회
4. TypeScript AST 분석으로 props 추출
5. 컴포넌트 메타데이터 업데이트
```
#### Figma → 컴포넌트 매핑
| Figma 요소 | 디자인 시스템 컴포넌트 |
|------------|------------------------|
| Button, Btn | `Button` / `SsmButton` |
| Text | `Text` / `SsmText` |
| Input, TextField | `Input` / `SsmInput` |
| Checkbox | `Check` / `SsmCheck` |
| Tag, Label, Badge | `Tag` / `SsmTag` |
| Chip | `Chip` / `SsmChip` |
| Tab, Tabs | `Tab` / `SsmTab` |
### 3. CodeGenerator (`services/code-generator.ts`)
Figma 데이터를 기반으로 React/Vue 코드를 생성합니다.
#### 코드 생성 과정
```
1. Figma 노드 트리 순회
2. 각 노드를 디자인 시스템 컴포넌트에 매핑
3. 매핑된 컴포넌트로 JSX/Template 생성
4. Import 문 자동 생성
5. 프리뷰 HTML/이미지 생성 (선택적)
```
#### 생성 파일
| 파일 | 설명 |
|------|------|
| `ComponentName.tsx` / `.vue` | 컴포넌트 코드 |
| `ComponentName.html` | 브라우저 미리보기 |
| `ComponentName.png` | 스크린샷 (Puppeteer 사용) |
| `metadata.json` | 요청 메타데이터 |
---
## 개발 방식
### MCP 프로토콜 구현
Palette는 [Model Context Protocol](https://modelcontextprotocol.io/) 표준을 따릅니다.
#### 제공 기능
| 기능 | 설명 |
|------|------|
| **Tools** | `convert_figma_to_react`, `convert_figma_to_vue`, `list_design_system_components`, `analyze_figma_file` |
| **Prompts** | `convert-design-to-component`, `explore-design-system` |
| **Resources** | `palette://design-system/react/components`, `palette://design-system/vue/components` |
### 실행 모드
#### 1. Local 모드 (stdio)
개발 환경이나 Cursor에서 직접 실행할 때 사용합니다.
```bash
# 직접 실행
yarn dev
# npx로 실행
npx palette-mcp
```
- stdio transport 사용
- Figma Desktop MCP 연결 가능 (로컬호스트 접근)
#### 2. Remote 모드 (Smithery)
Smithery.ai 클라우드에서 실행됩니다.
```typescript
// smithery.ts
export default createSmitheryServer({
figmaAccessToken: config.figmaAccessToken,
useFigmaMcp: false, // 로컬호스트 접근 불가
});
```
- Smithery SDK transport 사용
- REST API만 사용 (MCP 비활성화)
---
## 디자인 패턴
### 1. MCP-First + Fallback
```typescript
async getFigmaData(url: string): Promise<FigmaFile> {
// 1. MCP 서버 시도
if (this.useMCP && this.mcpClient) {
try {
const mcpData = await this.mcpClient.getFileData(fileId);
if (mcpData) return this.transformMCPResponse(mcpData);
} catch (error) {
console.warn('MCP 실패, REST API로 폴백');
}
}
// 2. REST API 폴백
return this.fetchFromRestApi(fileId);
}
```
### 2. Lazy Loading
무거운 의존성(Puppeteer 등)은 필요할 때만 로드합니다.
```typescript
let puppeteer: any = null;
async function loadPuppeteer() {
if (!puppeteer) {
puppeteer = (await import('puppeteer')).default;
}
return puppeteer;
}
```
### 3. 캐시 기반 동기화
GitHub에서 가져온 컴포넌트 정보는 캐시되어 성능을 최적화합니다.
```typescript
class CacheManager {
private cache: Map<string, CacheEntry>;
private readonly TTL = 24 * 60 * 60 * 1000; // 24시간
async get(key: string): Promise<T | null> {
const entry = this.cache.get(key);
if (entry && !this.isExpired(entry)) {
return entry.data;
}
return null;
}
}
```
---
## 환경 변수
| 변수명 | 필수 | 설명 | 기본값 |
|--------|------|------|--------|
| `FIGMA_ACCESS_TOKEN` | O | Figma Personal Access Token | - |
| `GITHUB_TOKEN` | X | GitHub 토큰 (동기화용) | - |
| `FIGMA_MCP_SERVER_URL` | X | Figma MCP 서버 URL | `http://127.0.0.1:3845/mcp` |
| `USE_FIGMA_MCP` | X | MCP 사용 여부 | `true` |