hwp-mcp
Reads, converts, renders, and edits Korean Hangul .hwp/.hwpx documents through MCP-compatible AI, with writing limited to .hwpx.
Read and extract body text, tables as Markdown, images, headers/footers, footnotes, equations, fields, metadata, and page definitions.
Convert HWP/HWPX to Markdown; list and extract embedded images; inspect fields and BinData entries.
Render pages as SVG or HTML and render OWPML equation scripts as SVG.
Edit .hwpx text with find/replace, template filling, paragraph/cell/field updates, and paragraph append/delete.
Modify tables by adding/deleting rows or columns, setting cell text, and merging cells horizontally or vertically.
Apply character and paragraph styles; insert/replace/delete images; create new .hwpx documents.
Limitations: .hwp write is unsupported, cross-format saves are rejected, and some features like real table insertion, textbox extraction, endnotes, and charts are experimental or missing.
Allows extracting tables from HWP and HWPX documents and converting them into Markdown format for structured data representation.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@hwp-mcp Read the content of report.hwp and extract all tables"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
hwp-mcp
A server that allows MCP-compatible AIs like Claude, Cursor, and ChatGPT to read, modify, and create Hangul documents (.hwp / .hwpx).
hwp-mcp is a Model Context Protocol (MCP) server that enables AI agents to directly handle Hancom Office documents. It supports not only reading, but also text modification, template filling, and creating new documents.
What is this project?
This project is divided into two parts:
🔧 What rhwp did (Core Engine) — Edward Kim's rhwp is an open-source engine that reverse-engineered the closed Hangul formats (HWP 5.0 binary, HWPX/OWPML) and implemented them in Rust + WebAssembly. Parsing, extraction of tables, images, equations, and headers, SVG rendering, and Hancom-compatible Field API — all these core capabilities are provided by rhwp. Without rhwp, this project would not exist.
🤝 What
hwp-mcpdid (Agent Adapter) — A thin MCP server layer built on top of@rhwp/core. What we added:Agent-friendly tool signatures like
read_hwp,fill_hwp_template, andreplace_hwp_text— allowing LLMs like Claude/Cursor to call them in natural language.A scenario-focused traversal walker that dumps body text, tables, images, headers, footers, footnotes, and equations all at once.
Usability layers such as automatic table cell merging and automatic footnote/equation consolidation.
A
.hwpxZIP-level mutation layer to bypass the round-trip limitations of rhwp 0.7.7'sexportHwpx(the key to enabling actual writing).The npm
hwp-mcppackage (one-line installation) + Node.js WASM bootstrap.
Summary: An adapter that allows AI to truly read and write Hangul documents. Please send all gratitude for the open Hangul capabilities to the rhwp project 🙏
Related MCP server: HWP-MCP
Installation
Claude Code
claude mcp add hwp-mcp -- npx -y hwp-mcpClaude Desktop / Cursor / VS Code (settings JSON)
{
"mcpServers": {
"hwp-mcp": {
"command": "npx",
"args": ["-y", "hwp-mcp"]
}
}
}Requires Node.js 20 or higher.
Tool List
These are the 34 MCP tools exposed by hwp-mcp v0.2. Reading/rendering supports both .hwp and .hwpx, while writing is exclusive to .hwpx.
Reading (5)
Tool |
|
| Description |
| ✅ | ✅ | Body + Tables (Markdown) + Image list at once |
| ✅ | ✅ | Integrated text: Body + Headers + Footers + Footnotes + Equations |
| ✅ | ✅ | Tables as GitHub Markdown (with cell merging) |
| ✅ | ✅ | List of embedded images (mime, bytes) |
| ✅ | ✅ | Extract images to disk |
Meta / Query (5)
Tool |
|
| Description |
| ✅ | ✅ | Version, pages, fonts, stats for tables/images/footnotes/equations |
| ✅ | ✅ | Paper size, margins, columns, header/footer margins per section |
| ✅ | ✅ | List of Hancom fields |
| ✅ | ✅ | Query field values |
| – | ✅ | List of |
Visual Rendering (4)
Tool |
|
| Description |
| ✅ | ✅ | Specific page → SVG (inline/file) |
| ✅ | ✅ | Batch SVG for all pages |
| ✅ | ✅ | Page → HTML |
| – | – | OWPML equation script → SVG |
Writing — Text (5)
Tool |
| Description |
| ✅ | Find and replace specific strings |
| ✅ | Multiple placeholders like |
| ✅ | Replace entire text of the Nth paragraph |
| ✅ | Directly set text in a table cell (row, column) |
| ✅ | Set field values |
Writing — Structure (9)
Tool |
| Description |
| ✅ | New paragraph at the end of the body |
| ✅ | Delete the Nth paragraph |
| ✅ | New row at the end of a table |
| ✅ | Delete a table row |
| ✅ | New column at the end of a table (in all rows) |
| ✅ | Delete a table column |
| ✅ | Horizontal cell merge (colSpan) |
| ✅ | Vertical cell merge (rowSpan) |
| ✅ | Replace embedded image |
Writing — Formatting (2)
Tool |
| Description |
| ✅ | Text color, bold, italic, underline, size (adds charPr) |
| ✅ | Paragraph alignment, indentation, line spacing (adds paraPr) |
Writing — Images / Tables / New (4)
Tool |
| Description |
| ✅ | Add new image (BinData + manifest + |
| ✅ | Delete BinData/ entry |
| ⚠️ | Insert new OWPML table (experimental — file valid, rhwp recognition incomplete) |
| ✅ | Create new |
Content Extraction Matrix
Content | Extraction | Notes |
Body paragraph text | ✅ |
|
Tables (incl. merged cells) | ✅ |
|
Embedded images | ✅ | Extract PNG/JPG/BMP, etc. |
Headers / Footers | ✅ |
|
Footnotes | ✅ |
|
Equations | ✅ | OWPML script format (e.g., |
Page SVG render | ✅ |
|
Textbox body | ❌ | rhwp's |
Endnotes | – | Not supported by rhwp (footnotes only) |
Charts | ❌ | After v0.3 |
Writing Matrix
Task |
|
| Notes |
Single text replacement | ❌ | ✅ |
|
Fill multiple placeholders | ❌ | ✅ |
|
Replace entire paragraph text | ❌ | ✅ |
|
Direct table cell modification | ❌ | ✅ |
|
Set field value | ❌ | ✅ |
|
Append / Delete paragraph | ❌ | ✅ |
|
Append / Delete table row | ❌ | ✅ |
|
Replace / Delete image | ❌ | ✅ |
|
Create new document (text) | – | ✅ |
|
Create new document (table) | – | ⚠️ | Flattened as text rows (real OWPML table in v0.3) |
Insert new image | ❌ | ✅ |
|
Append / Delete table column | ❌ | ✅ |
|
Cell merge (horizontal/vertical) | ❌ | ✅ |
|
Text formatting (color/bold/italic/underline/size) | ❌ | ✅ |
|
Paragraph formatting (align/indent/spacing) | ❌ | ✅ |
|
Insert new table (real OWPML) | ❌ | ⚠️ |
|
Insert new header/footer | ❌ | ❌ | v0.3 |
Charts/Bookmarks/Style definitions | ❌ | ❌ | v0.3 |
.hwpbinary writing is not supported in v0.2 due to theexportHwpround-trip limitations of rhwp 0.7.7. Please save as.hwpxin Hancom Office before using writing tools, or wait for the v0.3 release.
Usage Examples
Reading Government Hangul Documents
나: /Users/me/2026년_시행계획.hwpx 읽어줘
AI: # 2026년_시행계획.hwpx
형식: .HWPX | 문단: 153개 | 표: 15개 | 이미지: 2개
Ⅰ. 추진 배경
□ (글로벌 현황) 전세계 AI 솔루션 시장 규모는 ...
### 표 9 (7행 x 4열)
| 도메인 | 입력 데이터 | 학습 내용 | 산업AI 솔루션 적용 기능 예시 |
| --- | --- | --- | --- |
| 기계 | · 센서 데이터 로그 ... | ... | ... |Filling Templates
나: /path/to/form.hwpx 에서 {{이름}}=남대현, {{회사}}=포텐랩 으로 채워줘
AI: 저장 완료 (saved): form_filled.hwpx
총 2건 치환 (2 replacements)
'{{이름}}' → 1건
'{{회사}}' → 1건Text Replacement
나: /path/to/doc.hwpx 의 "산업AI" 를 "산업-AI" 로 바꿔줘
AI: '산업AI' → '산업-AI': 18건 교체 (replaced 18)
저장 (saved): doc_modified.hwpxCreating a New .hwpx
나: employees.hwpx 에 "사원 명부" 와 "두 번째 줄" 두 줄을 가진 문서 만들어줘
AI: HWPX 문서 생성 완료 (created): employees.hwpxExtracting Images
나: /path/to/document.hwpx 에서 이미지 빼줘
AI: 이미지 2개를 추출했습니다 (extracted 2 images):
저장 위치: /path/to/document_images
- image_001.bmp
- image_002.bmpRendering Pages to SVG (for visual analysis)
나: /path/to/document.hwpx 의 첫 페이지를 SVG로 보여줘
AI: <svg xmlns="..." width="793" height="1122" viewBox="...">
<defs>...</defs>
...
</svg>Or save to disk:
나: /path/to/document.hwpx 모든 페이지 SVG로 저장해줘
AI: 9/9 페이지 SVG 저장 (rendered 9/9 pages):
저장 위치: /path/to/document_pages
- page_001.svg
- page_002.svg ...Limitations
Known constraints of hwp-mcp v0.2:
.hwpwriting not supported — Reading works for both.hwp/.hwpx. Writing is.hwpxonly. Calling writing tools on.hwpinput will return a clear error message. Please save as.hwpxin Hancom Office or wait for v0.3.Cross-format saving denied —
.hwpxinput is saved only as.hwpx.Headers/Footers/Footnotes extractable; Textboxes/Endnotes/Equations in v0.3 — In
read_hwp_textresults, headers are marked as--- headers ---, footers as--- footers ---, and footnotes as--- footnotes ---blocks. Textbox body, endnotes, and equation extraction are planned for v0.3.No matching if search term spans two text nodes — e.g., if one
<hp:t>ends in "Industry" and the next starts with "AI", "IndustryAI" will not match. This is the same limitation as Hancom's hwpctl.Tables in
create_hwpx_documentare flattened to text rows in v0.2 — Real OWPML tables will be in v0.3.
How does it work?
Reading:
@rhwp/core(rhwp's Rust+WASM parser) traverses sections, paragraphs, tables (including merged cells), and images.Writing (.hwpx): Directly parses
Contents/section*.xmlinside the ZIP archive, performs search/replace on<hp:t>text nodes, and re-packages (mimetype stored as per spec). This is a layer to bypass rhwp'sexportHwpx()round-trip issues.New Documents: Created using rhwp's
createBlankDocument+insertText, then saved viaexportHwpx(text round-trip is stable).
Credits
rhwp (@edwardkim) — Core parser, renderer, and Field API. All the work that opened up the closed Hangul format is the foundation of this project. If possible, please support that project as well: https://github.com/edwardkim/rhwp
hwp-mcp — A thin MCP adapter built on top of rhwp that turns it into tools that AI agents can call in natural language. All core capabilities belong to rhwp; we are just the wiring that connects it to LLMs.
Coverage
Area | Coverage |
Reading/Extraction | ~90% |
Rendering | ~85% (SVG · HTML · Equation SVG · Canvas excluded as it's for browsers) |
Writing — Text | ~95% |
Writing — Structure | ~90% (Rows · Columns · Merging · 4 types of images) |
Writing — Formatting | ~70% (Text + Paragraph) |
Meta / Fields | ~85% |
Overall Weighted | ~85% |
Remaining major items for v0.3: .hwp binary writing, charts, style definitions/application, textbox body extraction, hwpctl 30 Actions (intentionally excluded).
English
hwp-mcp is an MCP server for reading and writing Korean Hangul (.hwp / .hwpx) documents from Claude / Cursor / ChatGPT and any MCP-compatible client. Read works for both formats; write currently supports .hwpx (find/replace, template fill, create new doc) — .hwp write is planned for v0.3. Built on top of rhwp (Rust + WebAssembly HWP engine by Edward Kim, MIT). Install: claude mcp add hwp-mcp -- npx -y hwp-mcp.
License
MIT.
Available Tools
34 toolsappend_hwp_paragraphA
Append a new paragraph to the end of an .hwpx document body. Clones the last paragraph's structure (paraPr/charPr/style refs) and replaces text. Args: file_path, text, output_path (optional).
Inputs: file_path (required), text (required), output_path.
append_hwp_table_columnB
Append a new column to the Nth table in an .hwpx. cells is a JSON string array of cell texts (one per row, top-to-bottom). Args: file_path, table_index, cells, output_path (optional).
Inputs: file_path (required), table_index (required), cells (required), output_path.
append_hwp_table_rowB
Append a new row to the Nth table (0-based) in an .hwpx. cells is a JSON string array of cell texts (length should match table column count). Args: file_path, table_index, cells, output_path (optional).
Inputs: file_path (required), table_index (required), cells (required), output_path.
apply_hwp_paragraph_styleA
Apply paragraph formatting (alignment·indent·line_spacing) to the Nth paragraph in an .hwpx. Adds a new paraPr to header.xml and retargets the paragraph's paraPrIDRef. align: LEFT|CENTER|RIGHT|JUSTIFY|DISTRIBUTE. Args: file_path, paragraph_index, align/indent/line_spacing (any subset), output_path (optional).
Inputs: file_path (required), paragraph_index (required), align, indent, +2 more.
apply_hwp_text_styleA
Apply formatting (color/bold/italic/underline/font_size) to the first run that contains target_text. Adds a new charPr to header.xml and retargets the matching hp:run. Color is a 6-digit hex (e.g. 'FF0000'). Args: file_path, target_text, color/bold/italic/underline/font_size (any subset), output_path (optional).
Inputs: file_path (required), target_text (required), color, bold, +4 more.
create_hwpx_documentA
Create a new .hwpx file from a JSON content list of {type:'text',text} items. Tables (type:'table',headers,rows) are rendered as flat text rows in v0.2. Args: output_path (must end with .hwpx), content (JSON string of items).
Inputs: output_path (required), content (required).
delete_hwp_imageB
Delete a BinData/ ZIP entry inside an .hwpx (effectively removes the embedded image bytes). Args: file_path, target (basename or full entry), output_path (optional).
Inputs: file_path (required), target (required), output_path.
delete_hwp_paragraphB
Delete the Nth paragraph (0-based) from an .hwpx body. Args: file_path, index, output_path (optional).
Inputs: file_path (required), index (required), output_path.
delete_hwp_table_columnB
Delete the Mth column (0-based) from the Nth table in an .hwpx (removes one hp:tc from every row). Args: file_path, table_index, col_index, output_path (optional).
Inputs: file_path (required), table_index (required), col_index (required), output_path.
delete_hwp_table_rowC
Delete the Mth row (0-based) from the Nth table (0-based) in an .hwpx. Args: file_path, table_index, row_index, output_path (optional).
Inputs: file_path (required), table_index (required), row_index (required), output_path.
extract_hwp_imagesA
Save every embedded image to disk. Args: file_path, output_dir (optional; defaults to _images/).
Inputs: file_path (required), output_dir.
fill_hwp_templateC
Fill multiple placeholders in an HWPX template. replacements is a JSON object string, e.g. {"{{name}}":"Kim","{{company}}":"Acme"}. v0.2: .hwpx only. Args: file_path, replacements, output_path (optional).
Inputs: file_path (required), replacements (required), output_path.
get_hwp_field_valueB
Get a Hancom field's current value by name. Args: file_path, name.
Inputs: file_path (required), name (required).
get_hwp_infoC
Get document metadata (version, page count, section count, fonts used, totals for tables/images/footnotes/equations/headers/footers). Args: file_path.
Inputs: file_path (required).
get_hwp_page_defB
Get per-section page definition (paper size, margins, columns) and section properties. Useful for understanding document layout. Args: file_path.
Inputs: file_path (required).
insert_hwp_imageA
Insert a new image into an .hwpx — adds the file to BinData/, registers it in content.hpf, and appends a paragraph with an inline hp:pic. Args: file_path, source_path, ext (png/jpg/bmp/gif; auto from source_path if omitted), output_path (optional).
Inputs: file_path (required), source_path (required), ext, output_path.
insert_hwp_tableB
Insert a real OWPML table at the end of an .hwpx body (proper hp:tbl/hp:tr/hp:tc). headers and rows are both JSON string arrays — headers is a single-row array of strings, rows is an array of row arrays. Args: file_path, headers, rows, output_path (optional).
Inputs: file_path (required), headers (required), rows (required), output_path.
list_hwp_bindataA
List ZIP entries under BinData/ inside an .hwpx (image and binary attachments). Useful before replace_hwp_image. Args: file_path.
Inputs: file_path (required).
list_hwp_fieldsA
List Hancom-style fields (<hp:fldBegin>/end pairs) in the document, with name and type when available. Useful before fill_hwp_template. Args: file_path.
Inputs: file_path (required).
list_hwp_imagesC
List embedded images (mime, byte length, locator) in an HWP/HWPX file. Args: file_path.
Inputs: file_path (required).
merge_hwp_cells_horizontalB
Merge horizontal cells in a row of a table by setting colSpan on the first cell and removing the absorbed cells. Args: file_path, table_index, row, col_start, col_count (>=2), output_path (optional).
Inputs: file_path (required), table_index (required), row (required), col_start (required), +2 more.
merge_hwp_cells_verticalC
Merge vertical cells across rows in a single column by setting rowSpan on the first cell and removing absorbed cells in following rows. Args: file_path, table_index, col, row_start, row_count (>=2), output_path (optional).
Inputs: file_path (required), table_index (required), col (required), row_start (required), +2 more.
read_hwpA
Read full HWP/HWPX document content as text + tables (markdown) + image listing. Args: file_path (absolute path).
Inputs: file_path (required).
read_hwp_tablesC
Extract every table from an HWP/HWPX file as GitHub-flavored markdown. Args: file_path.
Inputs: file_path (required).
read_hwp_textB
Extract plain body text from an HWP/HWPX file (no tables, no images). Args: file_path.
Inputs: file_path (required).
render_hwp_all_pagesA
Render every page of an HWP/HWPX as SVG files in a directory. Args: file_path, output_dir (default _pages/), max_pages (optional limit).
Inputs: file_path (required), output_dir, max_pages.
render_hwp_equation_svgA
Render an OWPML equation script (e.g. 'TIMES LEFT ( {a} over {b} RIGHT )') to SVG. Args: script, font_size (HWP units, default 1300), color (default 0).
Inputs: script (required), font_size, color.
render_hwp_htmlA
Render a single page of an HWP/HWPX as HTML. Useful for AI consumption when SVG isn't ideal. Args: file_path, page (0-based, default 0), output_path (optional).
Inputs: file_path (required), page, output_path.
render_hwp_pageA
Render a single page of an HWP/HWPX document as SVG. If output_path is omitted, the raw SVG string is returned inline (useful for direct LLM consumption). Args: file_path, page (0-based, default 0), output_path (optional).
Inputs: file_path (required), page, output_path.
replace_hwp_imageB
Replace an embedded image inside an .hwpx by overwriting its BinData/ ZIP entry with new file contents. target accepts either basename ('image1.bmp') or full entry path ('BinData/image1.bmp'). Args: file_path, target, source_path, output_path (optional).
Inputs: file_path (required), target (required), source_path (required), output_path.
replace_hwp_textB
Find and replace text in an HWPX file. v0.2: only .hwpx is supported as input/output. Args: file_path, old_text, new_text, output_path (optional).
Inputs: file_path (required), old_text (required), new_text (required), output_path.
set_hwp_cell_textC
Replace a single cell's text in a table inside an .hwpx. Args: file_path, table_index, row, col (all 0-based), text, output_path (optional).
Inputs: file_path (required), table_index (required), row (required), col (required), +2 more.
set_hwp_field_valueA
Set a Hancom field's value by name in an .hwpx (writes the new text between the matching <hp:fldBegin name=...> and <hp:fldEnd>). Use list_hwp_fields first to discover names. Args: file_path, name, value, output_path (optional).
Inputs: file_path (required), name (required), value (required), output_path.
set_hwp_paragraph_textA
Replace the entire text of the Nth paragraph (0-based) in an .hwpx body with new text. The paragraph attributes (paraPr/style refs) are preserved; runs are collapsed into a single hp:run with the new text. Args: file_path, index, text, output_path (optional).
Inputs: file_path (required), index (required), text (required), output_path.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 34 tools
Each tool has a clearly distinct purpose, targeting specific aspects of HWP/HWPX manipulation (paragraphs, tables, images, fields, etc.). Overlaps like read_hwp, read_hwp_text, and read_hwp_tables are clearly differentiated by their output focus.
All tools follow a consistent verb_noun (or verb_noun_noun) snake_case pattern, such as append_hwp_paragraph, extract_hwp_images, set_hwp_cell_text. No mixing of conventions.
34 tools is a large set, but given the complexity of the HWP format and the need for granular control over paragraphs, tables, images, fields, and rendering, the count is justified and not excessive.
The tool surface covers CRUD-like operations for paragraphs, tables, images, and fields, plus reading and rendering. Minor gaps exist (e.g., no explicit delete document), but the core workflow is well-supported.
Maintenance
Related MCP Connectors
One MCP server for the services your AI needs: memory, files, Microsoft 365, kanban and more.
Hosted MCP server: convert PDFs to clean, LLM-ready Markdown with tables, formulas and OCR.
Document conversion MCP server: PDF to Markdown, image OCR, spreadsheet parsing.
The Needle MCP server enables semantic search on documents stored in files like PDFs, DOCX, and XLSX by connecting AI applications to external data sources. It provides capabilities to create and manage document collections, perform natural language searches on stored content, and retrieve relevant information without requiring exact keyword matches.
Related MCP Servers
- FlicenseAqualityDmaintenanceAn MCP server that enables LLMs to convert HWP and HWPX documents into Markdown for analysis and processing. It supports document conversion via local file paths or Base64 content across various MCP-compatible clients.2-
- FlicenseNot gradedqualityNot gradedmaintenanceAn MCP server that enables AI models to control Hancom Office Hanword (HWP) documents on Windows. It allows for the automated creation, editing, and management of Korean word processor files, including text formatting and table manipulation.-
- AlicenseNot gradedqualityDmaintenanceAn MCP server for reading, editing, and creating Hangul Word Processor (.hwpx) files. It enables users to extract text, perform find-and-replace operations, and modify font styles through automated XML patching.35 npmMIT
- AlicenseNot gradedqualityCmaintenanceMCP server for AI-driven editing of HWPX (Korean word processor) documents, providing 132 tools for text, tables, images, and more.MIT