Skip to main content
Glama
Dayoooun

HWPX MCP Server

by Dayoooun
README.md
# HWPX MCP Server - Enhanced Edition

[![GitHub](https://img.shields.io/badge/GitHub-Dayoooun%2Fhwp--extension-blue?logo=github)](https://github.com/Dayoooun/hwpx-mcp)
[![Fork](https://img.shields.io/badge/Forked%20from-mjyoo2%2Fhwp--extension-gray?logo=github)](https://github.com/mjyoo2/hwp-extension)

> πŸš€ **Original ν”„λ‘œμ νŠΈλ₯Ό Forkν•˜μ—¬ μ•ˆμ •μ„±κ³Ό κΈ°λŠ₯을 λŒ€ν­ κ°œμ„ ν•œ λ²„μ „μž…λ‹ˆλ‹€.**

AI 도ꡬ(Claude λ“±)와 μ—°λ™ν•˜μ—¬ ν•œκΈ€(HWPX) λ¬Έμ„œλ₯Ό μžλ™μœΌλ‘œ νŽΈμ§‘ν•  수 μžˆλŠ” MCP(Model Context Protocol) μ„œλ²„μž…λ‹ˆλ‹€.

---

## 🌍 Cross-Platform Support

**λͺ¨λ“  μš΄μ˜μ²΄μ œμ—μ„œ μž‘λ™ν•©λ‹ˆλ‹€!**

| OS | MCP μ„œλ²„ | HWPX νŽΈμ§‘ | κ²°κ³Όλ¬Ό 확인 |
|:---:|:---:|:---:|:---|
| βœ… Windows | βœ… | βœ… | ν•œμ»΄μ˜€ν”ΌμŠ€ |
| βœ… macOS | βœ… | βœ… | ν•œμ»΄μ˜€ν”ΌμŠ€ Mac |
| βœ… Linux | βœ… | βœ… | ν•œμ»΄μ˜€ν”ΌμŠ€ Linux / LibreOffice* |

> **μ™œ κ°€λŠ₯ν•œκ°€μš”?**
> HWPX νŒŒμΌμ€ **ZIP + XML ꡬ쑰**μž…λ‹ˆλ‹€. ν•œκΈ€ ν”„λ‘œκ·Έλž¨ 없이도 Node.js만으둜 μ™„λ²½ν•˜κ²Œ 읽고 μ“Έ 수 μžˆμŠ΅λ‹ˆλ‹€.
>
> *LibreOfficeλŠ” HWPXλ₯Ό μ œν•œμ μœΌλ‘œ μ§€μ›ν•©λ‹ˆλ‹€. μ™„λ²½ν•œ ν˜Έν™˜μ„ μœ„ν•΄ ν•œμ»΄μ˜€ν”ΌμŠ€ μ‚¬μš©μ„ ꢌμž₯ν•©λ‹ˆλ‹€.

---

## ✨ Enhanced Features (κ°œμ„ λœ κΈ°λŠ₯)

원본 ν”„λ‘œμ νŠΈ λŒ€λΉ„ λ‹€μŒκ³Ό 같은 **핡심 λ¬Έμ œλ“€μ„ ν•΄κ²°**ν–ˆμŠ΅λ‹ˆλ‹€:

### πŸ”§ Critical Bug Fixes

| 문제 | 원본 μƒνƒœ | κ°œμ„  ν›„ |
|------|----------|---------|
| **ν…Œμ΄λΈ” μ €μž₯ μ‹€νŒ¨** | μ…€ μˆ˜μ • ν›„ μ €μž₯해도 변경사항 사라짐 | βœ… μ™„λ²½ν•˜κ²Œ μ €μž₯됨 |
| **ν…μŠ€νŠΈ κ²ΉμΉ¨ ν˜„μƒ** | μ €μž₯ ν›„ ν•œκΈ€μ—μ„œ μ—΄λ©΄ κΈ€μžκ°€ 겹쳐 ν‘œμ‹œ | βœ… 정상 ν‘œμ‹œ |
| **파일 손상** | μ €μž₯ μ‹œ 가끔 파일이 손상됨 | βœ… μ›μžμ  μ“°κΈ°λ‘œ 100% μ•ˆμ „ |
| **닀쀑 μ…€ 손상** | 같은 행에 μ—¬λŸ¬ μ…€ μˆ˜μ • μ‹œ XML 손상 | βœ… 인덱슀 κ΄€λ¦¬λ‘œ μ•ˆμ „ |
| **μžκ°„/쀄간격 손싀** | μ €μž₯ ν›„ μŠ€νƒ€μΌ 정보 μœ μ‹€ | βœ… λͺ¨λ“  μŠ€νƒ€μΌ 보쑴 |

### πŸ›  Technical Improvements

1. **Atomic File Writing (μ›μžμ  파일 μ“°κΈ°)**
   - μž„μ‹œ 파일 β†’ ZIP 검증 β†’ μ›μžμ  이동
   - μ €μž₯ 쀑 였λ₯˜ λ°œμƒν•΄λ„ 원본 파일 보호

2. **Smart Lineseg Reset (슀마트 쀄 λ ˆμ΄μ•„μ›ƒ μ΄ˆκΈ°ν™”)**
   - ν…μŠ€νŠΈ μˆ˜μ • μ‹œ `lineseg` μžλ™ μ΄ˆκΈ°ν™”
   - ν•œκΈ€ ν”„λ‘œκ·Έλž¨μ΄ μ—΄ λ•Œ μžλ™μœΌλ‘œ μ€„λ°”κΏˆ μž¬κ³„μ‚°
   - ν…μŠ€νŠΈ κ²ΉμΉ¨ ν˜„μƒ μ™„μ „ ν•΄κ²°

3. **Depth-based XML Parsing (깊이 기반 XML νŒŒμ‹±)**
   - κΈ°μ‘΄ lazy regex의 쀑첩 ꡬ쑰 μ˜€μΈμ‹ 문제 ν•΄κ²°
   - λ³΅μž‘ν•œ ν…Œμ΄λΈ”(쀑첩 ν…Œμ΄λΈ”, subList λ“±) μ™„λ²½ 지원

4. **Complete Style Preservation (μŠ€νƒ€μΌ μ™„μ „ 보쑴)**
   - `charPr`, `spacing` λ“± 원본 μŠ€νƒ€μΌ 100% μœ μ§€
   - λΆˆμ™„μ „ν•œ 직렬화 둜직 제거둜 데이터 무결성 보μž₯

5. **Safe Multi-Cell Updates (μ•ˆμ „ν•œ 닀쀑 μ…€ μ—…λ°μ΄νŠΈ)**
   - 같은 ν–‰(row)의 μ—¬λŸ¬ 셀을 λ™μ‹œμ— μˆ˜μ •ν•΄λ„ μ•ˆμ „
   - 행별 κ·Έλ£Ήν™” + μ—­μˆœ 처리둜 인덱슀 손상 λ°©μ§€

---

## πŸ“¦ Installation

### 1. MCP μ„œλ²„ μ„€μΉ˜

```bash
git clone https://github.com/Dayoooun/hwpx-mcp.git
cd hwpx-mcp/mcp-server
npm install
npm run build
```

### 2. MCP ν΄λΌμ΄μ–ΈνŠΈ μ„€μ •

μ•„λž˜μ—μ„œ μ‚¬μš©ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μ„ νƒν•˜μ„Έμš”.

---

#### πŸ–₯️ Claude Desktop

**μ„€μ • 파일 μœ„μΉ˜:**
| OS | 경둜 |
|----|------|
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| Linux | `~/.config/Claude/claude_desktop_config.json` |

**μ„€μ • λ‚΄μš©:**
```json
{
  "mcpServers": {
    "hwpx-mcp": {
      "command": "node",
      "args": ["C:/path/to/hwpx-mcp/mcp-server/dist/index.js"]
    }
  }
}
```

> ⚠️ Windowsμ—μ„œλŠ” κ²½λ‘œμ— `\\` λ˜λŠ” `/` μ‚¬μš© (예: `C:/Users/username/hwpx-mcp/...`)

---

#### πŸ’» Claude Code (CLI)

**방법 1: ν”„λ‘œμ νŠΈλ³„ μ„€μ •** (`.mcp.json` νŒŒμΌμ„ ν”„λ‘œμ νŠΈ λ£¨νŠΈμ— 생성)
```json
{
  "mcpServers": {
    "hwpx-mcp": {
      "command": "node",
      "args": ["/path/to/hwpx-mcp/mcp-server/dist/index.js"]
    }
  }
}
```

**방법 2: μ „μ—­ μ„€μ •** (`~/.claude/settings.json`)
```json
{
  "mcpServers": {
    "hwpx-mcp": {
      "command": "node",
      "args": ["/path/to/hwpx-mcp/mcp-server/dist/index.js"]
    }
  }
}
```

**방법 3: CLI λͺ…λ Ήμ–΄λ‘œ μΆ”κ°€**
```bash
claude mcp add hwpx-mcp node /path/to/hwpx-mcp/mcp-server/dist/index.js
```

---

#### πŸ”· Cursor

**μ„€μ • 파일:** `~/.cursor/mcp.json` (μ—†μœΌλ©΄ 생성)

```json
{
  "mcpServers": {
    "hwpx-mcp": {
      "command": "node",
      "args": ["/path/to/hwpx-mcp/mcp-server/dist/index.js"]
    }
  }
}
```

λ˜λŠ” **Cursor Settings > MCP** μ—μ„œ 직접 μΆ”κ°€ κ°€λŠ₯

---

#### πŸ†š VS Code (MCP ν™•μž₯ μ‚¬μš© μ‹œ)

**μ„€μ • 파일:** `.vscode/mcp.json` (ν”„λ‘œμ νŠΈ 폴더 λ‚΄)

```json
{
  "servers": {
    "hwpx-mcp": {
      "command": "node",
      "args": ["${workspaceFolder}/../hwpx-mcp/mcp-server/dist/index.js"]
    }
  }
}
```

> `${workspaceFolder}` λ³€μˆ˜λ₯Ό ν™œμš©ν•˜λ©΄ μƒλŒ€ 경둜 μ§€μ • κ°€λŠ₯

---

#### πŸ› οΈ 기타 MCP ν΄λΌμ΄μ–ΈνŠΈ

일반적인 MCP μ„€μ • ν˜•μ‹:
```json
{
  "mcpServers": {
    "hwpx-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/hwpx-mcp/mcp-server/dist/index.js"]
    }
  }
}
```

**경둜 μ˜ˆμ‹œ:**
| OS | 경둜 μ˜ˆμ‹œ |
|----|----------|
| Windows | `C:/Users/username/hwpx-mcp/mcp-server/dist/index.js` |
| macOS | `/Users/username/hwpx-mcp/mcp-server/dist/index.js` |
| Linux | `/home/username/hwpx-mcp/mcp-server/dist/index.js` |

---

### 3. μ„€μΉ˜ 확인

ν΄λΌμ΄μ–ΈνŠΈ μž¬μ‹œμž‘ ν›„ MCP 도ꡬ λͺ©λ‘μ—μ„œ `hwpx-mcp` μ„œλ²„μ™€ 77개 도ꡬ가 ν‘œμ‹œλ˜λ©΄ 성곡!

---

## πŸ”Œ MCP Tools (77개)

### πŸ“ λ¬Έμ„œ 관리 (Document Management) - 5개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `create_document` | μƒˆ 빈 HWPX λ¬Έμ„œ 생성 | `title?`, `creator?` |
| `open_document` | HWPX λ¬Έμ„œ μ—΄κΈ° | `file_path` |
| `close_document` | μ—΄λ¦° λ¬Έμ„œ λ‹«κΈ° | `doc_id` |
| `save_document` | λ¬Έμ„œ μ €μž₯ (λ°±μ—…/무결성 검증 지원) | `doc_id`, `output_path?`, `create_backup?`, `verify_integrity?` |
| `list_open_documents` | ν˜„μž¬ μ—΄λ¦° λ¬Έμ„œ λͺ©λ‘ 쑰회 | - |

**λ³΄μ•ˆ λ²”μœ„:** ν˜„μž¬ npm μ„œλ²„μ™€ VS Code λ²ˆλ“€ μ„œλ²„ λͺ¨λ‘ 파일 경둜λ₯Ό μž‘μ—… 폴더 μ•ˆμœΌλ‘œ μ œν•œν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
μ ˆλŒ€κ²½λ‘œΒ·μƒμœ„κ²½λ‘œΒ·λ””λ ‰ν„°λ¦¬ 심볼릭 링크λ₯Ό ν†΅ν•œ μ™ΈλΆ€ 파일 접근이 κ°€λŠ₯ν•˜λ―€λ‘œ, μ‹ λ’°ν•˜λŠ” 둜컬 MCP
ν΄λΌμ΄μ–ΈνŠΈμ—μ„œλ§Œ μ‚¬μš©ν•˜κ³  OS κΆŒν•œ λ˜λŠ” μ»¨ν…Œμ΄λ„ˆλ‘œ μ ‘κ·Ό λ²”μœ„λ₯Ό μ œν•œν•˜μ„Έμš”.
npm μ„œλ²„μ˜ μ €μž₯ μž„μ‹œ νŒŒμΌΒ·λ°±μ—… λ³΄ν˜ΈλŠ” 파일 μ ‘κ·Ό λ²”μœ„ μ œν•œμ„ λŒ€μ‹ ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

### πŸ“„ λ¬Έμ„œ 정보 (Document Info) - 5개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_document_text` | λ¬Έμ„œ 전체 ν…μŠ€νŠΈ μΆ”μΆœ | `doc_id` |
| `get_document_structure` | λ¬Έμ„œ ꡬ쑰 쑰회 (μ„Ήμ…˜/단락/ν…Œμ΄λΈ”/이미지 수) | `doc_id` |
| `get_document_metadata` | 메타데이터 쑰회 (제λͺ©, μ €μž, λ‚ μ§œ λ“±) | `doc_id` |
| `set_document_metadata` | 메타데이터 μˆ˜μ • | `doc_id`, `title?`, `creator?`, `subject?`, `description?` |
| `get_word_count` | κΈ€μžμˆ˜/λ‹¨μ–΄μˆ˜ 톡계 | `doc_id` |

### πŸ“ 단락 (Paragraphs) - 8개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_paragraphs` | 단락 λͺ©λ‘ 쑰회 (ν…μŠ€νŠΈ/μŠ€νƒ€μΌ 포함) | `doc_id`, `section_index?` |
| `get_paragraph` | νŠΉμ • 단락 상세 정보 | `doc_id`, `section_index`, `paragraph_index` |
| `insert_paragraph` | μƒˆ 단락 μ‚½μž… | `doc_id`, `section_index`, `after_index`, `text` |
| `delete_paragraph` | 단락 μ‚­μ œ | `doc_id`, `section_index`, `paragraph_index` |
| `update_paragraph_text` | 단락 ν…μŠ€νŠΈ λ‚΄μš© μˆ˜μ • | `doc_id`, `section_index`, `paragraph_index`, `text`, `run_index?` |
| `append_text_to_paragraph` | κΈ°μ‘΄ 단락에 ν…μŠ€νŠΈ μΆ”κ°€ | `doc_id`, `section_index`, `paragraph_index`, `text` |
| `copy_paragraph` | 단락을 λ‹€λ₯Έ μœ„μΉ˜λ‘œ 볡사 | `doc_id`, `source_section`, `source_paragraph`, `target_section`, `target_after` |
| `move_paragraph` | 단락을 λ‹€λ₯Έ μœ„μΉ˜λ‘œ 이동 | `doc_id`, `source_section`, `source_paragraph`, `target_section`, `target_after` |

### 🎨 ν…μŠ€νŠΈ μŠ€νƒ€μΌ (Text Styling) - 4개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_text_style` | κΈ€μž μ„œμ‹ 쑰회 (폰트/크기/색상 λ“±) | `doc_id`, `section_index`, `paragraph_index`, `run_index?` |
| `set_text_style` | κΈ€μž μ„œμ‹ μ„€μ • | `doc_id`, `section_index`, `paragraph_index`, `bold?`, `italic?`, `underline?`, `strikethrough?`, `font_name?`, `font_size?`, `font_color?`, `background_color?` |
| `get_paragraph_style` | 문단 μ„œμ‹ 쑰회 (μ •λ ¬/쀄간격/μ—¬λ°± λ“±) | `doc_id`, `section_index`, `paragraph_index` |
| `set_paragraph_style` | 문단 μ„œμ‹ μ„€μ • | `doc_id`, `section_index`, `paragraph_index`, `align?`, `line_spacing?`, `margin_*?`, `first_line_indent?` |

### πŸ” 검색/μΉ˜ν™˜ (Search & Replace) - 4개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `search_text` | λ¬Έμ„œ λ‚΄ ν…μŠ€νŠΈ 검색 (μ •κ·œμ‹ 지원, **ν…Œμ΄λΈ” μ…€ 포함**) | `doc_id`, `query`, `case_sensitive?`, `regex?`, `include_tables?` |
| `replace_text` | ν…μŠ€νŠΈ μ°Ύμ•„ λ°”κΎΈκΈ° | `doc_id`, `old_text`, `new_text`, `case_sensitive?`, `regex?`, `replace_all?` |
| `replace_text_in_cell` | **νŠΉμ • ν…Œμ΄λΈ” μ…€ λ‚΄ ν…μŠ€νŠΈ μΉ˜ν™˜** | `doc_id`, `section_index`, `table_index`, `row`, `col`, `old_text`, `new_text` |
| `batch_replace` | μ—¬λŸ¬ ν…μŠ€νŠΈ 일괄 μΉ˜ν™˜ | `doc_id`, `replacements[]` (old_text, new_text 쌍 λ°°μ—΄) |

### πŸ“Š ν…Œμ΄λΈ” (Tables) - 12개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_tables` | λ¬Έμ„œ λ‚΄ λͺ¨λ“  ν…Œμ΄λΈ” λͺ©λ‘ | `doc_id` |
| `get_table` | νŠΉμ • ν…Œμ΄λΈ” 전체 데이터 쑰회 | `doc_id`, `section_index`, `table_index` |
| `get_table_cell` | νŠΉμ • μ…€ λ‚΄μš© 쑰회 | `doc_id`, `section_index`, `table_index`, `row`, `col` |
| `update_table_cell` | μ…€ λ‚΄μš© μˆ˜μ • (μŠ€νƒ€μΌ 보쑴) | `doc_id`, `section_index`, `table_index`, `row`, `col`, `text`, `char_shape_id?` |
| `set_cell_properties` | μ…€ 속성 μ„€μ • (크기/배경색/μ •λ ¬) | `doc_id`, `section_index`, `table_index`, `row`, `col`, `width?`, `height?`, `background_color?`, `vertical_align?` |
| `insert_table` | μƒˆ ν…Œμ΄λΈ” μ‚½μž… | `doc_id`, `section_index`, `after_index`, `rows`, `cols`, `width?` |
| `insert_table_row` | ν…Œμ΄λΈ”μ— ν–‰ μ‚½μž… | `doc_id`, `section_index`, `table_index`, `after_row`, `cell_texts?` |
| `delete_table_row` | ν…Œμ΄λΈ”μ—μ„œ ν–‰ μ‚­μ œ | `doc_id`, `section_index`, `table_index`, `row_index` |
| `insert_table_column` | ν…Œμ΄λΈ”μ— μ—΄ μ‚½μž… | `doc_id`, `section_index`, `table_index`, `after_col` |
| `delete_table_column` | ν…Œμ΄λΈ”μ—μ„œ μ—΄ μ‚­μ œ | `doc_id`, `section_index`, `table_index`, `col_index` |
| `insert_nested_table` | **μ…€ μ•ˆμ— 쀑첩 ν…Œμ΄λΈ” μ‚½μž… (ν‘œ μ•ˆμ— ν‘œ)** | `doc_id`, `section_index`, `parent_table_index`, `row`, `col`, `nested_rows`, `nested_cols`, `data?` |
| `get_table_as_csv` | ν…Œμ΄λΈ”μ„ CSV ν˜•μ‹μœΌλ‘œ μΆ”μΆœ | `doc_id`, `section_index`, `table_index`, `delimiter?` |

### πŸ“ νŽ˜μ΄μ§€ μ„€μ • (Page Settings) - 2개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_page_settings` | νŽ˜μ΄μ§€ μ„€μ • 쑰회 (μš©μ§€ 크기/μ—¬λ°±) | `doc_id`, `section_index?` |
| `set_page_settings` | νŽ˜μ΄μ§€ μ„€μ • λ³€κ²½ | `doc_id`, `section_index?`, `width?`, `height?`, `margin_*?`, `orientation?` |

### πŸ–ΌοΈ 이미지 (Images) - 5개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_images` | λ¬Έμ„œ λ‚΄ λͺ¨λ“  이미지 λͺ©λ‘ | `doc_id` |
| `insert_image` | 이미지 파일 μ‚½μž… (BinData μžλ™ 등둝) | `doc_id`, `section_index`, `after_index`, `image_path`, `width?`, `height?` |
| `update_image_size` | κΈ°μ‘΄ 이미지 크기 λ³€κ²½ | `doc_id`, `section_index`, `image_index`, `width`, `height` |
| `delete_image` | 이미지 μ‚­μ œ | `doc_id`, `section_index`, `image_index` |
| `render_mermaid` | **Mermaid λ‹€μ΄μ–΄κ·Έλž¨μ„ μ΄λ―Έμ§€λ‘œ μ‚½μž…** | `doc_id`, `mermaid_code`, `after_index`, `section_index?`, `width?`, `height?`, `theme?`, `background_color?` |

### ✏️ λ„ν˜• (Shapes) - 3개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `insert_line` | μ„  λ„ν˜• μ‚½μž… | `doc_id`, `section_index`, `after_index`, `x1`, `y1`, `x2`, `y2`, `stroke_color?`, `stroke_width?` |
| `insert_rect` | μ‚¬κ°ν˜• λ„ν˜• μ‚½μž… | `doc_id`, `section_index`, `after_index`, `x`, `y`, `width`, `height`, `fill_color?`, `stroke_color?` |
| `insert_ellipse` | 타원 λ„ν˜• μ‚½μž… | `doc_id`, `section_index`, `after_index`, `cx`, `cy`, `rx`, `ry`, `fill_color?`, `stroke_color?` |

### πŸ“‘ 머리글/λ°”λ‹₯κΈ€ (Header/Footer) - 4개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_header` | 머리글 λ‚΄μš© 쑰회 | `doc_id`, `section_index?` |
| `set_header` | 머리글 μ„€μ • | `doc_id`, `text`, `section_index?`, `apply_page_type?` (both/even/odd) |
| `get_footer` | λ°”λ‹₯κΈ€ λ‚΄μš© 쑰회 | `doc_id`, `section_index?` |
| `set_footer` | λ°”λ‹₯κΈ€ μ„€μ • | `doc_id`, `text`, `section_index?`, `apply_page_type?` (both/even/odd) |

### πŸ“Œ 각주/λ―Έμ£Ό (Footnotes/Endnotes) - 4개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_footnotes` | λ¬Έμ„œ λ‚΄ λͺ¨λ“  각주 λͺ©λ‘ | `doc_id` |
| `insert_footnote` | νŠΉμ • μœ„μΉ˜μ— 각주 μ‚½μž… | `doc_id`, `section_index`, `paragraph_index`, `text` |
| `get_endnotes` | λ¬Έμ„œ λ‚΄ λͺ¨λ“  λ―Έμ£Ό λͺ©λ‘ | `doc_id` |
| `insert_endnote` | νŠΉμ • μœ„μΉ˜μ— λ―Έμ£Ό μ‚½μž… | `doc_id`, `section_index`, `paragraph_index`, `text` |

### πŸ”— 뢁마크/ν•˜μ΄νΌλ§ν¬ (Bookmarks/Hyperlinks) - 4개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_bookmarks` | λ¬Έμ„œ λ‚΄ λͺ¨λ“  뢁마크 λͺ©λ‘ | `doc_id` |
| `insert_bookmark` | νŠΉμ • μœ„μΉ˜μ— 뢁마크 μ‚½μž… | `doc_id`, `section_index`, `paragraph_index`, `name` |
| `get_hyperlinks` | λ¬Έμ„œ λ‚΄ λͺ¨λ“  ν•˜μ΄νΌλ§ν¬ λͺ©λ‘ | `doc_id` |
| `insert_hyperlink` | ν•˜μ΄νΌλ§ν¬ μ‚½μž… | `doc_id`, `section_index`, `paragraph_index`, `url`, `text` |

### βž— μˆ˜μ‹ (Equations) - 2개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_equations` | λ¬Έμ„œ λ‚΄ λͺ¨λ“  μˆ˜μ‹ λͺ©λ‘ | `doc_id` |
| `insert_equation` | μˆ˜μ‹ μ‚½μž… (HWP μˆ˜μ‹ 슀크립트 ν˜•μ‹) | `doc_id`, `section_index`, `after_index`, `script` |

### πŸ’¬ λ©”λͺ¨ (Memos/Comments) - 3개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_memos` | λ¬Έμ„œ λ‚΄ λͺ¨λ“  λ©”λͺ¨/주석 λͺ©λ‘ | `doc_id` |
| `insert_memo` | λ©”λͺ¨/주석 μ‚½μž… | `doc_id`, `section_index`, `paragraph_index`, `content`, `author?` |
| `delete_memo` | λ©”λͺ¨/주석 μ‚­μ œ | `doc_id`, `memo_id` |

### πŸ“š μ„Ήμ…˜ (Sections) - 5개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_sections` | λ¬Έμ„œ λ‚΄ λͺ¨λ“  μ„Ήμ…˜ λͺ©λ‘ | `doc_id` |
| `insert_section` | μƒˆ μ„Ήμ…˜ μ‚½μž… | `doc_id`, `after_index` |
| `delete_section` | μ„Ήμ…˜ μ‚­μ œ | `doc_id`, `section_index` |
| `get_section_xml` | **μ„Ήμ…˜ Raw XML 쑰회 (AI λ¬Έμ„œ μ‘°μž‘μš©)** | `doc_id`, `section_index?` |
| `set_section_xml` | **μ„Ήμ…˜ Raw XML ꡐ체 (HWPML ν˜•μ‹ ν•„μˆ˜)** | `doc_id`, `xml`, `section_index?`, `validate?` |

### 🎭 μŠ€νƒ€μΌ μ •μ˜ (Style Definitions) - 4개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_styles` | λ¬Έμ„œμ— μ •μ˜λœ μŠ€νƒ€μΌ λͺ©λ‘ | `doc_id` |
| `get_char_shapes` | κΈ€μž λͺ¨μ–‘(CharShape) μ •μ˜ λͺ©λ‘ | `doc_id` |
| `get_para_shapes` | 문단 λͺ¨μ–‘(ParaShape) μ •μ˜ λͺ©λ‘ | `doc_id` |
| `apply_style` | 단락에 μŠ€νƒ€μΌ 적용 | `doc_id`, `section_index`, `paragraph_index`, `style_id` |

### πŸ“° 단 μ„€μ • (Column Layout) - 2개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `get_column_def` | 단(Column) μ„€μ • 쑰회 | `doc_id`, `section_index?` |
| `set_column_def` | 단 μ„€μ • λ³€κ²½ (닀단 νŽΈμ§‘) | `doc_id`, `count`, `section_index?`, `type?`, `same_size?`, `gap?` |

### πŸ“€ 내보내기 (Export) - 2개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `export_to_text` | λ¬Έμ„œλ₯Ό ν…μŠ€νŠΈ 파일둜 내보내기 | `doc_id`, `output_path` |
| `export_to_html` | λ¬Έμ„œλ₯Ό HTML 파일둜 내보내기 | `doc_id`, `output_path` |

### ↩️ μ‹€ν–‰ μ·¨μ†Œ (Undo/Redo) - 2개

| Tool | μ„€λͺ… | μ£Όμš” νŒŒλΌλ―Έν„° |
|------|------|--------------|
| `undo` | λ§ˆμ§€λ§‰ λ³€κ²½ μ‹€ν–‰ μ·¨μ†Œ | `doc_id` |
| `redo` | μ‹€ν–‰ μ·¨μ†Œν•œ λ³€κ²½ λ‹€μ‹œ μ‹€ν–‰ | `doc_id` |

---

### μ‚¬μš© μ˜ˆμ‹œ

```typescript
// λ¬Έμ„œ μ—΄κΈ°
await mcp.open_document({ file_path: "report.hwpx" })

// ν…Œμ΄λΈ” μ…€ μˆ˜μ •
await mcp.update_table_cell({
  doc_id: "...",
  section_index: 0,
  table_index: 0,
  row: 0,
  col: 1,
  text: "μˆ˜μ •λœ λ‚΄μš©"
})

// 쀑첩 ν…Œμ΄λΈ” μ‚½μž… (ν‘œ μ•ˆμ— ν‘œ)
await mcp.insert_nested_table({
  doc_id: "...",
  section_index: 0,
  parent_table_index: 0,
  row: 1,
  col: 2,
  nested_rows: 2,
  nested_cols: 2,
  data: [["A1", "A2"], ["B1", "B2"]]
})

// Mermaid λ‹€μ΄μ–΄κ·Έλž¨ μ‚½μž…
await mcp.render_mermaid({
  doc_id: "...",
  mermaid_code: "graph TD; A-->B; B-->C;",
  after_index: 0,
  theme: "default"
})

// μ €μž₯
await mcp.save_document({ doc_id: "..." })
```

#### ν…Œμ΄λΈ” μ…€ 검색/μΉ˜ν™˜ μ›Œν¬ν”Œλ‘œμš°

λ™μΌν•œ ν…μŠ€νŠΈκ°€ μ—¬λŸ¬ 곳에 μžˆμ„ λ•Œ **νŠΉμ • μœ„μΉ˜**만 μˆ˜μ •ν•˜λŠ” 방법:

```typescript
// 1. ν…Œμ΄λΈ” 포함 κ²€μƒ‰μœΌλ‘œ μœ„μΉ˜ νŒŒμ•…
const results = await mcp.search_text({
  doc_id: "...",
  query: "μˆ˜μ •λŒ€μƒ",
  include_tables: true  // ν…Œμ΄λΈ” μ…€ 포함
})
// κ²°κ³Ό: [{ text: "μˆ˜μ •λŒ€μƒ", location: { type: "table", tableIndex: 2, row: 3, col: 1 } }, ...]

// 2. μ›ν•˜λŠ” μœ„μΉ˜μ˜ μ…€λ§Œ μ •λ°€ μΉ˜ν™˜
await mcp.replace_text_in_cell({
  doc_id: "...",
  section_index: 0,
  table_index: 2,  // 검색 κ²°κ³Όμ—μ„œ ν™•μΈν•œ μœ„μΉ˜
  row: 3,
  col: 1,
  old_text: "μˆ˜μ •λŒ€μƒ",
  new_text: "μƒˆλ‘œμš΄λ‚΄μš©"
})
```

---

## πŸ“‹ Supported Format

| 포맷 | ν™•μž₯자 | 읽기 | μ“°κΈ° |
|------|--------|:----:|:----:|
| HWPX | .hwpx | βœ… | βœ… |
| HWP | .hwp | ❌ | ❌ |

> **Note**: HWP(λ°”μ΄λ„ˆλ¦¬) νŒŒμΌμ€ μ§€μ›ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. ν•œμ»΄μ˜€ν”ΌμŠ€μ—μ„œ HWPX둜 λ³€ν™˜ ν›„ μ‚¬μš©ν•˜μ„Έμš”.

---

## πŸ“ Release Notes

### v0.4.0 (Enhanced Search & Diagram Support)
- πŸ†• **New Feature**: `search_text`에 `include_tables` μ˜΅μ…˜ μΆ”κ°€ - ν…Œμ΄λΈ” μ…€ λ‚΄ ν…μŠ€νŠΈλ„ 검색
- πŸ†• **New Feature**: `replace_text_in_cell` - νŠΉμ • ν…Œμ΄λΈ” μ…€ λ‚΄ ν…μŠ€νŠΈλ§Œ μ •λ°€ μΉ˜ν™˜
- πŸ†• **New Feature**: `render_mermaid` - Mermaid λ‹€μ΄μ–΄κ·Έλž¨μ„ μ΄λ―Έμ§€λ‘œ λ¬Έμ„œμ— μ‚½μž…
  - Flowchart, Sequence, Class Diagram λ“± λͺ¨λ“  Mermaid 문법 지원
  - ν…Œλ§ˆ 선택 κ°€λŠ₯ (default, dark, forest, neutral)
- πŸ†• **New Feature**: `get_section_xml` / `set_section_xml` - μ„Ήμ…˜ Raw XML 직접 μ‘°μž‘
  - AI 기반 κ³ κΈ‰ λ¬Έμ„œ νŽΈμ§‘ μ‹œλ‚˜λ¦¬μ˜€ 지원
- πŸ”§ **Improvement**: `insert_image` μ™„μ „ κ°œμ„ 
  - BinData 폴더에 이미지 μžλ™ μ €μž₯
  - content.hpf λ§€λ‹ˆνŽ˜μŠ€νŠΈ μžλ™ 등둝
  - 파일 손상 없이 이미지 μ‚½μž… 보μž₯

### v0.3.1 (npm server maintenance)
- npm μ„œλ²„μ˜ μž„μ‹œ νŒŒμΌΒ·λ°±μ—… 링크 곡격 λ°©μ–΄ 및 μ €μž₯ μ‹€νŒ¨ μ‹œ 원본 보쑴
- λΆ„λ¦¬λœ ν…μŠ€νŠΈ νƒœκ·Έ μ €μž₯ λˆ„λ½ μˆ˜μ •, μ˜μ‘΄μ„± κ°±μ‹  및 이식 κ°€λŠ₯ν•œ νšŒκ·€ ν…ŒμŠ€νŠΈ 보완
- κΈ°μ‘΄ 파일 경둜 μ‚¬μš©λ²• μœ μ§€. μž‘μ—… 폴더 μ ‘κ·Ό μ œν•œ 및 μˆ˜μ‹ μ €μž₯ μˆ˜μ •μ€ ν¬ν•¨ν•˜μ§€ μ•ŠμŒ
### v0.3.0 (Nested Table Support)
- πŸ†• **New Feature**: `insert_nested_table` - ν…Œμ΄λΈ” μ…€ μ•ˆμ— 쀑첩 ν…Œμ΄λΈ” μ‚½μž… κΈ°λŠ₯
  - λΆ€λͺ¨ ν…Œμ΄λΈ”μ˜ νŠΉμ • 셀에 μƒˆ ν…Œμ΄λΈ”μ„ μ‚½μž…
  - 초기 데이터 μ§€μ • κ°€λŠ₯ (2D λ°°μ—΄)
  - HWPX ν‘œμ€€ ꡬ쑰(`treatAsChar`, `hp:subList`) μ™„λ²½ μ€€μˆ˜
- πŸ”§ **Improvement**: charSpacing νŒŒμ‹± κ°œμ„  (속성 μˆœμ„œ λ¬΄κ΄€ν•˜κ²Œ 처리)

### v0.2.1 (Critical Fix)
- πŸ”₯ **Critical Fix**: 같은 행에 μ—¬λŸ¬ μ…€ λ™μ‹œ μˆ˜μ • μ‹œ 파일 손상 문제 μ™„μ „ ν•΄κ²°
  - ν–‰(row)별 μ—…λ°μ΄νŠΈ κ·Έλ£Ήν™”λ‘œ 인덱슀 뢈일치 λ°©μ§€
  - μ—­μˆœ(descending) 처리둜 μ•ˆμ „ν•œ XML μˆ˜μ • 보μž₯

### v0.2.0 (Enhanced Edition)
- πŸ”₯ **Major Fix**: ν…μŠ€νŠΈ μˆ˜μ • μ‹œ lineseg μžλ™ μ΄ˆκΈ°ν™”λ‘œ κ²ΉμΉ¨ ν˜„μƒ μ™„μ „ ν•΄κ²°
- πŸ”§ **Bug Fix**: 쀑첩 ν…Œμ΄λΈ” κ΅¬μ‘°μ—μ„œ XML μš”μ†Œ 경계 μ˜€μΈμ‹ 문제 μˆ˜μ •
- πŸ›‘οΈ **Stability**: μ›μžμ  파일 μ“°κΈ°λ‘œ 파일 손상 λ°©μ§€
- πŸ“¦ **Preservation**: 원본 charPr/spacing μŠ€νƒ€μΌ μ™„μ „ 보쑴

### v0.1.0 (Original)
- 졜초 릴리슀 (mjyoo2/hwp-extension)

---

## πŸ™ Credits

- Original Project: [mjyoo2/hwp-extension](https://github.com/mjyoo2/hwp-extension)
- Enhanced by: [Dayoooun](https://github.com/Dayoooun)

---

## πŸ“„ License

MIT

---

## 🀝 Contributing

버그 리포트 및 κΈ°λŠ₯ μš”μ²­: [GitHub Issues](https://github.com/Dayoooun/hwpx-mcp/issues)