Skip to main content
Glama

hwp-mcp

A server that allows MCP-compatible AIs like Claude, Cursor, and ChatGPT to read, modify, and create Hangul documents (.hwp / .hwpx).

npm version npm downloads Built on rhwp License: MIT GitHub release

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-mcp did (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, and replace_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 .hwpx ZIP-level mutation layer to bypass the round-trip limitations of rhwp 0.7.7's exportHwpx (the key to enabling actual writing).

    • The npm hwp-mcp package (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-mcp

Claude 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

.hwp

.hwpx

Description

read_hwp

✅

✅

Body + Tables (Markdown) + Image list at once

read_hwp_text

✅

✅

Integrated text: Body + Headers + Footers + Footnotes + Equations

read_hwp_tables

✅

✅

Tables as GitHub Markdown (with cell merging)

list_hwp_images

✅

✅

List of embedded images (mime, bytes)

extract_hwp_images

✅

✅

Extract images to disk

Meta / Query (5)

Tool

.hwp

.hwpx

Description

get_hwp_info

✅

✅

Version, pages, fonts, stats for tables/images/footnotes/equations

get_hwp_page_def

✅

✅

Paper size, margins, columns, header/footer margins per section

list_hwp_fields

✅

✅

List of Hancom fields

get_hwp_field_value

✅

✅

Query field values

list_hwp_bindata

–

✅

List of .hwpx BinData/ entries

Visual Rendering (4)

Tool

.hwp

.hwpx

Description

render_hwp_page

✅

✅

Specific page → SVG (inline/file)

render_hwp_all_pages

✅

✅

Batch SVG for all pages

render_hwp_html

✅

✅

Page → HTML

render_hwp_equation_svg

–

–

OWPML equation script → SVG

Writing — Text (5)

Tool

.hwpx

Description

replace_hwp_text

✅

Find and replace specific strings

fill_hwp_template

✅

Multiple placeholders like {{name}}

set_hwp_paragraph_text

✅

Replace entire text of the Nth paragraph

set_hwp_cell_text

✅

Directly set text in a table cell (row, column)

set_hwp_field_value

✅

Set field values

Writing — Structure (9)

Tool

.hwpx

Description

append_hwp_paragraph

✅

New paragraph at the end of the body

delete_hwp_paragraph

✅

Delete the Nth paragraph

append_hwp_table_row

✅

New row at the end of a table

delete_hwp_table_row

✅

Delete a table row

append_hwp_table_column

✅

New column at the end of a table (in all rows)

delete_hwp_table_column

✅

Delete a table column

merge_hwp_cells_horizontal

✅

Horizontal cell merge (colSpan)

merge_hwp_cells_vertical

✅

Vertical cell merge (rowSpan)

replace_hwp_image

✅

Replace embedded image

Writing — Formatting (2)

Tool

.hwpx

Description

apply_hwp_text_style

✅

Text color, bold, italic, underline, size (adds charPr)

apply_hwp_paragraph_style

✅

Paragraph alignment, indentation, line spacing (adds paraPr)

Writing — Images / Tables / New (4)

Tool

.hwpx

Description

insert_hwp_image

✅

Add new image (BinData + manifest + <hp:pic>)

delete_hwp_image

✅

Delete BinData/ entry

insert_hwp_table

⚠️

Insert new OWPML table (experimental — file valid, rhwp recognition incomplete)

create_hwpx_document

✅

Create new .hwpx from text

Content Extraction Matrix

Content

Extraction

Notes

Body paragraph text

✅

read_hwp_text, read_hwp

Tables (incl. merged cells)

✅

read_hwp_tables as markdown

Embedded images

✅

Extract PNG/JPG/BMP, etc.

Headers / Footers

✅

--- headers --- / --- footers --- blocks in read_hwp_text result

Footnotes

✅

--- footnotes --- block at the end of result, format [1] body...

Equations

✅

OWPML script format (e.g., TIMES LEFT ( {a} over {b} RIGHT )), --- equations --- block

Page SVG render

✅

render_hwp_page

Textbox body

❌

rhwp's createShapeControl creates them, but getTextBoxControlIndex return pattern is implicit — trace in v0.3

Endnotes

–

Not supported by rhwp (footnotes only)

Charts

❌

After v0.3

Writing Matrix

Task

.hwp

.hwpx

Notes

Single text replacement

❌

✅

replace_hwp_text

Fill multiple placeholders

❌

✅

fill_hwp_template

Replace entire paragraph text

❌

✅

set_hwp_paragraph_text

Direct table cell modification

❌

✅

set_hwp_cell_text (specify row/col)

Set field value

❌

✅

set_hwp_field_value

Append / Delete paragraph

❌

✅

append_hwp_paragraph / delete_hwp_paragraph

Append / Delete table row

❌

✅

append_hwp_table_row / delete_hwp_table_row

Replace / Delete image

❌

✅

replace_hwp_image / delete_hwp_image

Create new document (text)

–

✅

create_hwpx_document

Create new document (table)

–

⚠️

Flattened as text rows (real OWPML table in v0.3)

Insert new image

❌

✅

insert_hwp_image

Append / Delete table column

❌

✅

append_hwp_table_column / delete_hwp_table_column

Cell merge (horizontal/vertical)

❌

✅

merge_hwp_cells_horizontal / merge_hwp_cells_vertical

Text formatting (color/bold/italic/underline/size)

❌

✅

apply_hwp_text_style

Paragraph formatting (align/indent/spacing)

❌

✅

apply_hwp_paragraph_style

Insert new table (real OWPML)

❌

⚠️

insert_hwp_table (experimental)

Insert new header/footer

❌

❌

v0.3

Charts/Bookmarks/Style definitions

❌

❌

v0.3

.hwp binary writing is not supported in v0.2 due to the exportHwp round-trip limitations of rhwp 0.7.7. Please save as .hwpx in 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.hwpx

Creating a New .hwpx

나: employees.hwpx 에 "사원 명부" 와 "두 번째 줄" 두 줄을 가진 문서 만들어줘

AI: HWPX 문서 생성 완료 (created): employees.hwpx

Extracting Images

나: /path/to/document.hwpx 에서 이미지 빼줘

AI: 이미지 2개를 추출했습니다 (extracted 2 images):
    저장 위치: /path/to/document_images
      - image_001.bmp
      - image_002.bmp

Rendering 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:

  • .hwp writing not supported — Reading works for both .hwp/.hwpx. Writing is .hwpx only. Calling writing tools on .hwp input will return a clear error message. Please save as .hwpx in Hancom Office or wait for v0.3.

  • Cross-format saving denied — .hwpx input is saved only as .hwpx.

  • Headers/Footers/Footnotes extractable; Textboxes/Endnotes/Equations in v0.3 — In read_hwp_text results, 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_document are 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*.xml inside 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's exportHwpx() round-trip issues.

  • New Documents: Created using rhwp's createBlankDocument + insertText, then saved via exportHwpx (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 tools
append_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

    A3.5/5.0

    Scored across 34 tools

    Disambiguation5/5

    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.

    Naming Consistency5/5

    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.

    Tool Count4/5

    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.

    Completeness4/5

    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

    ActivityMaintained
    ResponsivenessLimited data

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      A
      quality
      D
      maintenance
      An 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
      -
    • F
      license
      Not graded
      quality
      Not graded
      maintenance
      An 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.
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      An 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 npm
      MIT