beomzh

hwpConverMdMCP

Community beomzh
Updated

hwpConverMd레포의 mcp

hwpConverMdMCP

HWP/HWPX 파일을 Markdown으로 변환하는 hwpConverMd 프로젝트의 MCP(Model Context Protocol) 서버입니다.

Claude Desktop, Cursor, Claude Code 등 MCP 클라이언트에서 HWP 문서 변환 기능을 직접 사용할 수 있습니다.

아키텍처

MCP 클라이언트 (Claude Desktop / Cursor / etc.)
        │
        │  stdio 또는 Streamable HTTP
        ▼
  hwpConverMdMCP (Node.js MCP Server)
        │
        │  HTTP API (multipart/form-data)
        ▼
  hwpConverMd (Python FastAPI Server)

전제조건

  • Node.js >= 18.0.0
  • hwpConverMd Python 서버가 실행 중이어야 합니다

hwpConverMd 서버 실행

# hwpConverMd 프로젝트 디렉토리에서
cd ../hwpConverMd

# Docker로 실행 (권장)
docker compose up --build

# 또는 직접 실행
pip install -r requirements.txt
uvicorn app.main:app --host 0.0.0.0 --port 8000

서버가 정상 동작하면 http://localhost:8000 에서 {"status": "ok"} 응답을 확인할 수 있습니다.

설치

npm install
npm run build

MCP Tools

Tool 설명 파라미터
convert_hwp_to_md 로컬 파일 경로로 HWP/HWPX → Markdown 변환 filePath: 파일 경로
convert_hwp_content_to_md Base64 인코딩 콘텐츠로 변환 content: Base64 문자열, filename: 파일명 (.hwp/.hwpx)

사용법

1. Claude Desktop에서 사용 (stdio)

claude_desktop_config.json 파일에 다음을 추가합니다:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.jsonWindows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "hwp-converter": {
      "command": "node",
      "args": ["/absolute/path/to/hwpConverMdMCP/dist/transport/stdio.js"],
      "env": {
        "HWP_API_URL": "http://localhost:8000"
      }
    }
  }
}

개발 모드로 사용하려면:

{
  "mcpServers": {
    "hwp-converter": {
      "command": "npx",
      "args": ["tsx", "/absolute/path/to/hwpConverMdMCP/src/transport/stdio.ts"],
      "env": {
        "HWP_API_URL": "http://localhost:8000"
      }
    }
  }
}

2. Cursor에서 사용 (stdio)

프로젝트 루트에 .cursor/mcp.json 파일을 생성합니다:

{
  "mcpServers": {
    "hwp-converter": {
      "command": "node",
      "args": ["/absolute/path/to/hwpConverMdMCP/dist/transport/stdio.js"],
      "env": {
        "HWP_API_URL": "http://localhost:8000"
      }
    }
  }
}

3. Claude Code에서 사용 (stdio)

claude mcp add hwp-converter \
  -e HWP_API_URL=http://localhost:8000 \
  -- node /absolute/path/to/hwpConverMdMCP/dist/transport/stdio.js

4. Streamable HTTP 모드 (웹 클라이언트용)

HTTP 서버를 시작합니다:

# 빌드된 버전
npm run start:http

# 또는 개발 모드
npm run dev:http

MCP 엔드포인트: http://localhost:3000/mcp

HTTP 클라이언트에서 연결:

# 초기화 요청 (POST)
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}'

환경변수

변수 설명 기본값
HWP_API_URL hwpConverMd Python API 서버 URL http://localhost:8000
MCP_HTTP_PORT Streamable HTTP 모드 포트 (HTTP 모드에서만 사용) 3000

개발

# 의존성 설치
npm install

# stdio 모드로 개발
npm run dev:stdio

# HTTP 모드로 개발
npm run dev:http

# 빌드
npm run build

# 빌드 후 실행
npm run start:stdio   # stdio 모드
npm run start:http    # HTTP 모드

Docker로 실행

MCP 서버와 hwpConverMd API 서버를 함께 Docker Compose로 실행할 수 있습니다.

사전 준비

프로젝트 디렉토리 구조가 다음과 같아야 합니다:

hwpToMd/
├── hwpConverMd/          # Python API 서버
└── hwpConverMdMCP/       # 이 프로젝트 (MCP 서버)

실행 방법

# hwpConverMdMCP 디렉토리에서
docker compose up --build -d

이 명령으로 두 서비스가 동시에 기동됩니다:

서비스 컨테이너 포트 역할
api hwpConverMd API 8000 HWP → Markdown 변환 엔진
mcp MCP 서버 3000 MCP 프로토콜 인터페이스

중요: MCP 컨테이너의 HWP_API_URLhttp://api:8000으로 설정되어 있어 Docker 내부 네트워크를 통해 API 서버에 접근합니다.

수정이 필요한 부분

docker-compose.yml에서 hwpConverMd 경로를 확인하세요:

services:
  api:
    build: ../hwpConverMd          # <-- hwpConverMd 프로젝트 경로 확인
    volumes:
      - ../hwpConverMd:/app        # <-- 동일 경로
      - ../hwpConverMd/temp:/app/temp
      - ../hwpConverMd/output:/app/output

만약 디렉토리 구조가 다르다면 이 경로들을 실제 hwpConverMd 프로젝트 위치로 수정해야 합니다.

기존 hwpConverMd 컨테이너와 연동

이미 hwpConverMd API가 별도로 실행 중이라면, MCP 컨테이너만 단독 실행할 수 있습니다:

# 1. 기존 hwpConverMd 네트워크 이름 확인
docker network ls | grep hwpconvermd

# 2. MCP 이미지 빌드
docker build -t hwp-converter-mcp .

# 3. 기존 네트워크에 연결하여 MCP 컨테이너 실행
docker run -d \
  --name hwp-mcp \
  --network hwpconvermd_default \
  -p 3000:3000 \
  -e HWP_API_URL=http://hwpconvermd-api-1:8000 \
  -e MCP_HTTP_PORT=3000 \
  hwp-converter-mcp

HWP_API_URL 수정 포인트: hwpconvermd-api-1 부분을 실제 API 컨테이너 이름으로 변경하세요. docker ps 명령으로 확인할 수 있습니다.

동작 확인

# 컨테이너 상태 확인
docker ps

# MCP 서버 로그 확인
docker logs hwp-mcp

# MCP 초기화 테스트
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}'

정상 응답 예시:

event: message
data: {"result":{"protocolVersion":"2025-03-26","capabilities":{"logging":{},"tools":{"listChanged":true}},"serverInfo":{"name":"hwp-converter-mcp","version":"1.0.0"}},"jsonrpc":"2.0","id":1}

종료

docker compose down

MCP 도구 호출 방법

기존에 API에 직접 curl로 문서를 던지던 방식과 비교:

[기존 방식 - 직접 API 호출]
curl -F "[email protected]" http://localhost:8000/api/v1/convert

[MCP 방식 - LLM이 도구를 호출]
사용자 → "이 문서 변환해줘" → LLM(Claude) → MCP tool call → API → 마크다운 → LLM이 분석

방법 A: MCP 클라이언트 앱 (Claude Desktop / Cursor)

설정 후 자연어로 요청하면 LLM이 자동으로 도구를 호출합니다:

"이 HWP 파일을 마크다운으로 변환해줘: /path/to/document.hwp"

방법 B: MCP Client SDK로 프로그래밍

// examples/mcp-client-basic.ts 참조
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const client = new Client({ name: "my-app", version: "1.0.0" });
await client.connect(
  new StreamableHTTPClientTransport(new URL("http://localhost:3000/mcp"))
);

// 파일 경로로 변환 (로컬 환경)
const result = await client.callTool({
  name: "convert_hwp_to_md",
  arguments: { filePath: "/path/to/document.hwp" },
});

// base64로 변환 (원격/K8s 환경)
const result2 = await client.callTool({
  name: "convert_hwp_content_to_md",
  arguments: { content: base64String, filename: "document.hwp" },
});

실행:

npx tsx examples/mcp-client-basic.ts /path/to/document.hwp

방법 C: curl로 직접 JSON-RPC 호출

# 1. 세션 초기화
SESSION_ID=$(curl -si --max-time 5 -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}' \
  | grep -i mcp-session-id | awk -F': ' '{print $2}' | tr -d '\r')

# 2. 도구 호출
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SESSION_ID" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"convert_hwp_to_md","arguments":{"filePath":"/path/to/doc.hwp"}}}'

두 도구의 사용 시나리오

도구 언제 사용 환경
convert_hwp_to_md MCP 서버와 같은 파일시스템 로컬 개발, Docker volume mount
convert_hwp_content_to_md 파일시스템이 분리된 환경 K8s, 원격 서버, 웹 클라이언트

LLM 연동

이 MCP 서버 자체가 LLM 연동 레이어입니다. 별도의 LLM 연동 프로젝트는 필요하지 않습니다.

연동 방식 비교

방식 설명 코드 필요
Claude Desktop/Cursor config.json 설정만으로 자동 연동 없음
Claude Code claude mcp add 명령으로 등록 없음
프로그래밍 (Anthropic API) MCP Client + Claude API 조합 examples/llm-with-mcp.ts
프로그래밍 (OpenAI 호환) MCP Client + 다른 LLM API 조합 동일 패턴

Anthropic Claude API + MCP 연동 예제

# 설치
npm install @anthropic-ai/sdk @modelcontextprotocol/sdk

# 실행
ANTHROPIC_API_KEY=sk-ant-... npx tsx examples/llm-with-mcp.ts /path/to/doc.hwp "이 문서를 요약해줘"

이 예제는 다음 흐름을 자동으로 수행합니다:

1. MCP 서버 연결
2. Claude API에 도구 목록 전달
3. Claude가 convert_hwp_content_to_md 도구 호출 결정
4. MCP 서버에서 HWP → Markdown 변환
5. 변환 결과를 Claude에게 전달
6. Claude가 사용자 요청(요약/분석)을 수행

자세한 코드는 examples/llm-with-mcp.ts를 참조하세요.

Kubernetes 배포

k8s_manifest/ 디렉토리에 API와 MCP를 별도 프로젝트로 분리하여 manifest가 준비되어 있습니다.

디렉토리 구조

k8s_manifest/
├── api/                   # hwpConverMd (Python API) - 별도 프로젝트
│   ├── serviceaccount.yaml
│   ├── rbac.yaml
│   ├── deployment.yaml        # Deployment + Service
│   └── networkpolicy.yaml
└── mcp/                   # hwpConverMdMCP (MCP 서버) - 이 프로젝트
    ├── serviceaccount.yaml
    ├── rbac.yaml
    ├── configmap.yaml
    ├── deployment.yaml        # Deployment + Service
    ├── networkpolicy.yaml
    └── ingress.yaml

참고: api/ 디렉토리의 manifest는 hwpConverMd 프로젝트에서 별도 관리될 수 있습니다.여기서는 참조용으로 포함했으며, 실제 운영 시에는 각 프로젝트 레포에서 독립적으로 관리하세요.

보안 설정

항목 적용 내용
ServiceAccount 서비스별 전용 SA (hwp-api-sa, hwp-mcp-sa), automountServiceAccountToken: false
RBAC ConfigMap 읽기만 허용 (최소 권한)
SecurityContext runAsNonRoot, drop ALL capabilities, seccompProfile: RuntimeDefault
readOnlyRootFilesystem MCP: true / API: false (Python __pycache__ 등 쓰기 필요)
NetworkPolicy default-deny-all + 명시적 허용만 (mcp→api, ingress→mcp)
Pod Security Standards namespace baseline enforce, restricted warn/audit
ResourceQuota namespace 전체 CPU/Memory/Pod 수 상한

배포 순서

# 1. 공통 리소스 (네임스페이스, 기본 정책)
kubectl apply -f k8s_manifest/common/

# 2. MCP 서버 (이 프로젝트)
kubectl apply -f k8s_manifest/mcp/

수정이 필요한 부분

1. 이미지 레지스트리
# mcp/deployment.yaml
image: your-registry.com/hwp-converter-mcp:1.0.0   # [수정 필요]
2. 도메인 + TLS (mcp/ingress.yaml)
tls:
  - hosts:
      - mcp.your-domain.com       # [수정 필요]
    secretName: hwp-mcp-tls       # [수정 필요]
rules:
  - host: mcp.your-domain.com     # [수정 필요]
3. Ingress Controller 네임스페이스 (api/networkpolicy.yaml, mcp/networkpolicy.yaml)
namespaceSelector:
  matchLabels:
    kubernetes.io/metadata.name: ingress-nginx   # [수정 필요] 실제 값 확인
kubectl get ns --show-labels | grep ingress
4. IngressClass (mcp/ingress.yaml)
kubectl get ingressclass   # 사용 가능한 클래스 확인

확인

# Pod 상태
kubectl get pods -n hwp-converter

# 헬스체크
kubectl port-forward -n hwp-converter svc/hwp-mcp-svc 3000:3000
curl http://localhost:3000/healthz
# → {"status":"ok","service":"hwp-converter-mcp"}

# RBAC 확인
kubectl auth can-i --as=system:serviceaccount:hwp-converter:hwp-mcp-sa \
  get configmaps -n hwp-converter
# → yes

kubectl auth can-i --as=system:serviceaccount:hwp-converter:hwp-mcp-sa \
  list pods -n hwp-converter
# → no (정상 - 최소 권한)

MCP Server · Populars

MCP Server · New