νκΈ mcp hwpx MCP Server
<p align="center"> <h1 align="center">π hwpx-mcp-server</h1> <p align="center"> <strong>νκΈ(HWPX) λ¬Έμλ₯Ό AIλ‘ μλννλ MCP μλ²</strong> </p> <p align="center"> νκΈ μλνλ‘μΈμ μμ΄ Β· μμ νμ΄μ¬ Β· ν¬λ‘μ€ νλ«νΌ </p> <p align="center"> <a href="https://pypi.org/project/hwpx-mcp-server/"><img src="https://img.shields.io/pypi/v/hwpx-mcp-server?style=flat-square&color=blue" alt="PyPI"></a> <a href="https://pypi.org/project/hwpx-mcp-server/"><img src="https://img.shields.io/pypi/pyversions/hwpx-mcp-server?style=flat-square" alt="Python"></a> <a href="https://github.com/airmang/hwpx-mcp-server/blob/main/LICENSE"><img src="https://img.shields.io/github/license/airmang/hwpx-mcp-server?style=flat-square" alt="License"></a> <a href="https://github.com/airmang/hwpx-mcp-server/actions"><img src="https://img.shields.io/github/actions/workflow/status/airmang/hwpx-mcp-server/test.yml?style=flat-square&label=tests" alt="Tests"></a> </p> </p> --- **hwpx-mcp-server**λ [Model Context Protocol(MCP)](https://modelcontextprotocol.io) νμ€μ λ°λ₯΄λ μλ²λ‘, [python-hwpx](https://github.com/airmang/python-hwpx) κΈ°λ°μμ HWPX λ¬Έμμ μ΄λ Β· κ²μ Β· νΈμ§ Β· μ μ₯μ AI ν΄λΌμ΄μΈνΈμμ μ§μ μνν μ μκ² ν©λλ€. > **Note** β μ΄ μλ²λ Open XML κΈ°λ° `.hwpx` ν¬λ§·μ μ§μν©λλ€. λ κ±°μ λ°μ΄λ리 `.hwp` ν¬λ§·μ μ§μ νΈμ§ λμμ΄ μλλλ€. <br> ## Why? κ΅λ΄ 곡곡기κ΄Β·νκ΅Β·κΈ°μ μμλ νκΈ λ¬Έμ κΈ°λ° μ λ¬΄κ° λ§€μ° λ§μ§λ§, μλνλ μ€λ«λμ OS/νλ‘κ·Έλ¨ μμ‘΄μ±μ΄ μ»Έμ΅λλ€. **hwpx-mcp-server**λ μ΄ μ μ½μ μ€μ΄λ λ° μ΄μ μ λ§μΆ₯λλ€. - β **OS 무κ΄** β Windows, macOS, Linuxμμ λμ - β **νκΈ μλνλ‘μΈμ λΆνμ** β μμ νμ΄μ¬ κΈ°λ° μ²λ¦¬ - β **AI λ€μ΄ν°λΈ** β Claude Desktop, VS Code, Gemini CLI λ± MCP ν΄λΌμ΄μΈνΈμ μ§μ μ°κ²° - β **Stateless κΈ°λ³Έ μ€κ³** β λꡬ νΈμΆλ§λ€ `filename`μ λͺ μν΄ μΌκ΄μ μΌλ‘ μ€ν <br> ## Use Cases - μ€μ μ¬μ© μ¬λ‘ 9κ° λ³΄κΈ°: [`docs/use-cases.md`](docs/use-cases.md) - μ’ ν© ν μ€νΈ 리ν¬νΈ: [`tests/hwpx_mcp_report_updated.md`](tests/hwpx_mcp_report_updated.md) <br> ## Quick Start ### 1. μ€μΉ & μ€ν [uv](https://docs.astral.sh/uv/getting-started/installation/) κΈ°μ€: ```bash uvx hwpx-mcp-server ``` λλ pip μ€μΉ: ```bash pip install hwpx-mcp-server hwpx-mcp-server ``` μꡬμ¬ν: - `Python >= 3.10` - `python-hwpx >= 1.9` ### 2. MCP ν΄λΌμ΄μΈνΈ μ€μ <details> <summary><b>Claude Desktop</b></summary> `claude_desktop_config.json`: ```json { "mcpServers": { "hwpx": { "command": "uvx", "args": ["hwpx-mcp-server"] } } } ``` </details> <details> <summary><b>Gemini CLI</b></summary> `~/.gemini/settings.json`: ```json { "mcpServers": { "hwpx": { "command": "uvx", "args": ["hwpx-mcp-server"] } } } ``` </details> <details> <summary><b>VS Code (Copilot Chat)</b></summary> `.vscode/mcp.json`: ```json { "servers": { "hwpx": { "command": "uvx", "args": ["hwpx-mcp-server"] } } } ``` </details> <details> <summary><b>Cursor / Windsurf</b></summary> κ° μλν° MCP μ€μ νμΌμ λμΌν λΈλ‘μ μΆκ°: ```json { "mcpServers": { "hwpx": { "command": "uvx", "args": ["hwpx-mcp-server"] } } } ``` </details> ### 3. μ μ‘ λͺ¨λ μ ν (Stdio + Streamable HTTP) κΈ°λ³Έ `stdio` μ¬μ©μ κΈ°μ‘΄κ³Ό λμΌν©λλ€. ```bash hwpx-mcp-server ``` λμΌν MCP λꡬ μΈνΈλ₯Ό Streamable HTTPλ‘ μ€νν μ μμ΅λλ€. ```bash hwpx-mcp-server --transport streamable-http --host 127.0.0.1 --port 8000 ``` νκ²½ λ³μλ‘λ λμΌνκ² μ μ΄ν μ μμ΅λλ€. - `HWPX_MCP_TRANSPORT` (`stdio` λλ `streamable-http`) - `HWPX_MCP_HOST` (κΈ°λ³Έκ°: `127.0.0.1`) - `HWPX_MCP_PORT` (κΈ°λ³Έκ°: `8000`) > μ°Έκ³ : HTTP μΈμ¦μ νμ¬ κ°λ° νΈμ μ€μ¬μΌλ‘ λ¨μνκ² μ μ§λμ΄ μμ΅λλ€. νλ‘λμ μ© μΈμ¦ ν μ μλ² μ§μ μ μ TODOλ‘ λ¨κ²¨λμμ΅λλ€. <br> ## Features κΈ°λ³Έ λͺ¨λμμ 30κ° λꡬ, κ³ κΈ λͺ¨λ(`HWPX_MCP_ADVANCED=1`)μμ μΆκ° 10κ° λκ΅¬κ° νμ±νλ©λλ€. ### π μ½κΈ° & νμ | λꡬ | μ€λͺ | |---|---| | `get_document_info` | λ¬Έμ λ©νλ°μ΄ν°/μΉμ /λ¬Έλ¨/ν κ°μ μ‘°ν | | `get_document_text` | λ¬Έμ μ 체 ν μ€νΈ μΆμΆ (`max_chars` μ§μ) | | `get_document_outline` | μ λͺ©/κ°μ ꡬ쑰 μΆμΆ | | `get_paragraph_text` | νΉμ λ¬Έλ¨ ν μ€νΈ μ‘°ν | | `get_paragraphs_text` | λ¬Έλ¨ λ²μ μ‘°ν | | `list_available_documents` | ν΄λ λ΄ `.hwpx` νμΌ λͺ©λ‘ μ‘°ν | ### π§Ύ λ³ν & μΆμΆ (μ λ ₯ νμ΄λ‘λ κΈ°λ°) | λꡬ | μ€λͺ | |---|---| | `hwpx_to_markdown` | HWPX μ λ ₯μ MarkdownμΌλ‘ λ³ν | | `hwpx_to_html` | HWPX μ λ ₯μ HTMLλ‘ λ³ν | | `hwpx_extract_json` | HWPX ꡬ쑰λ₯Ό JSONμΌλ‘ μΆμΆ | κ³΅ν΅ μ λ ₯ κ·μΉ: - μ λ ₯ μμ€λ `hwpx_base64` λλ `url` μ€ μ νν νλλ§ νμ© - `url`μ `https://...`λ§ νμ© κ³΅ν΅ μ΅μ : - `output`: `full` λλ `chunks` - `chunk_strategy`: `section` λλ `paragraph` - `max_chars_per_chunk`: μ²ν¬λΉ μ΅λ λ¬Έμ μ(κΈ°λ³Έκ°: `HWPX_MCP_MAX_CHARS_PER_CHUNK` λλ `8000`) <details> <summary><b>λ³ν/μΆμΆ μλ΅ μμ</b></summary> #### `hwpx_to_markdown` ```json { "markdown": "# Title\n\nParagraph...", "chunks": ["..."], "meta": { "source_type": "base64", "section_count": 2, "paragraph_count": 10, "table_count": 1, "figure_caption_count": 1 } } ``` #### `hwpx_to_html` ```json { "html": "<!doctype html><html>...</html>", "chunks": ["<section>...</section>"], "meta": { "source_type": "url", "image_policy": "omitted" } } ``` #### `hwpx_extract_json` ```json { "doc": { "title": "Title", "toc": [{ "level": 1, "text": "Title", "paragraph_index": 0 }], "sections": [{ "index": 0, "title": "Title", "paragraphs": [] }], "tables": [], "figures": [] }, "chunks": [{ "chunk_index": 0, "strategy": "section", "section": {} }], "meta": { "source_type": "base64" } } ``` </details> ### π κ²μ & μΉν | λꡬ | μ€λͺ | |---|---| | `find_text` | ν€μλ κ²μ + 컨ν μ€νΈ λ°ν | | `search_and_replace` | λ¨μΌ μΉν (split-run 보κ°) | | `batch_replace` | λ€μ€ μΉν μΌκ΄ μ€ν | ### βοΈ νΈμ§ | λꡬ | μ€λͺ | |---|---| | `add_heading` | μ λͺ©(ν€λ©) λ¬Έλ¨ μΆκ° | | `add_paragraph` / `insert_paragraph` / `delete_paragraph` | λ¬Έλ¨ μΆκ°/μ½μ /μμ | | `add_page_break` | νμ΄μ§ λλκΈ° μΆκ° | | `add_memo` / `remove_memo` | λ©λͺ¨ μΆκ°/μ κ±° | | `copy_document` | λ¬Έμ μμ λ³΅μ¬ | ### π ν | λꡬ | μ€λͺ | |---|---| | `add_table` / `get_table_text` | ν μμ±/μ‘°ν | | `set_table_cell_text` | μ ν μ€νΈ μμ | | `merge_table_cells` / `split_table_cell` | μ λ³ν©/λΆν | | `format_table` | ν ν€λ λ± κΈ°λ³Έ μμ μ μ© | ### π¨ μ€νμΌ | λꡬ | μ€λͺ | |---|---| | `format_text` | ν μ€νΈ λ²μ μμ μ μ©(κ΅΅κΈ°, κΈ°μΈμ, λ°μ€, μμ λ±) | | `create_custom_style` | 컀μ€ν μ€νμΌ μμ± | | `list_styles` | λ¬Έμ μ€νμΌ λͺ©λ‘ μ‘°ν | ### π¬ κ³ κΈ (μ΅μ ) `HWPX_MCP_ADVANCED=1`μΌ λ νμ±ν: | λꡬ | μ€λͺ | |---|---| | `package_parts` | OPC ννΈ λͺ©λ‘ μ‘°ν | | `package_get_xml` / `package_get_text` | ννΈ XML/ν μ€νΈ μ‘°ν | | `object_find_by_tag` / `object_find_by_attr` | XML μμ κ²μ | | `plan_edit` / `preview_edit` / `apply_edit` | νΈμ§ κ³ν/미리보기/μ μ© | | `validate_structure` / `lint_text_conventions` | ꡬ쑰 κ²μ¦/ν μ€νΈ λ¦°νΈ | <br> ## Configuration | λ³μ | μ€λͺ | κΈ°λ³Έκ° | |---|---|---| | `HWPX_MCP_MAX_CHARS` | ν μ€νΈ λ°ν λꡬ κΈ°λ³Έ μ΅λ κΈΈμ΄ | `10000` | | `HWPX_MCP_MAX_CHARS_PER_CHUNK` | λ³ν/μΆμΆ λꡬμ μ²ν¬ λΆν κΈ°λ³Έ κΈΈμ΄ | `8000` | | `HWPX_MCP_AUTOBACKUP` | `1`μ΄λ©΄ μ μ₯ μ `.bak` λ°±μ μμ± | `1` | | `HWPX_MCP_ADVANCED` | `1`μ΄λ©΄ κ³ κΈ λꡬ νμ±ν | `0` | | `HWPX_MCP_TRANSPORT` | μλ² μ μ‘ λͺ¨λ (`stdio`, `streamable-http`) | `stdio` | | `HWPX_MCP_HOST` | HTTP λ°μΈλ© νΈμ€νΈ | `127.0.0.1` | | `HWPX_MCP_PORT` | HTTP λ°μΈλ© ν¬νΈ | `8000` | | `LOG_LEVEL` | λ‘κ·Έ λ 벨 | `INFO` | νκ²½ λ³μ ν¬ν¨ MCP μ€μ μμ: ```json { "mcpServers": { "hwpx": { "command": "uvx", "args": ["hwpx-mcp-server"], "env": { "HWPX_MCP_MAX_CHARS": "12000", "HWPX_MCP_MAX_CHARS_PER_CHUNK": "8000", "HWPX_MCP_AUTOBACKUP": "1", "HWPX_MCP_ADVANCED": "0", "HWPX_MCP_TRANSPORT": "stdio", "HWPX_MCP_HOST": "127.0.0.1", "HWPX_MCP_PORT": "8000", "LOG_LEVEL": "INFO" } } } } ``` <br> ## Advanced <details> <summary><b>π¦ OPC ννΈ μ‘°ν</b></summary> κ³ κΈ λͺ¨λμμ λ¬Έμ λ΄λΆ ννΈλ₯Ό μ§μ μ‘°νν μ μμ΅λλ€. - `package_parts` - `package_get_xml` - `package_get_text` </details> <details> <summary><b>π§ νΈμ§ νμ΄νλΌμΈ</b></summary> κ³ κΈ λͺ¨λμμ `plan_edit β preview_edit β apply_edit` νλ¦μΌλ‘ λ³κ²½ κ³νμ κ²ν νκ³ μ μ©ν μ μμ΅λλ€. </details> <details> <summary><b>π§ͺ ꡬ쑰/κ·μΉ κ²μ¬</b></summary> κ³ κΈ λͺ¨λμμ λ€μ κ²μ¬ λꡬλ₯Ό μ¬μ©ν μ μμ΅λλ€. - `validate_structure` - `lint_text_conventions` </details> <br> ## Testing ```bash # ν μ€νΈ μμ‘΄μ± μ€μΉ python -m pip install -e ".[test]" # μ 체 ν μ€νΈ python -m pytest -q ``` λ‘컬 κΈ°μ€(2026-02-22) μ 체 ν μ€νΈκ° ν΅κ³Όνμ΅λλ€. - μ€μ μ¬μ© μ¬λ‘: `docs/use-cases.md` - μ’ ν© λ¦¬ν¬νΈ: `tests/hwpx_mcp_report_updated.md` - νκ· ν μ€νΈ: `tests/test_hwpx_report_regressions.py` <br> ## Architecture ```text hwpx-mcp-server βββ src/hwpx_mcp_server/ β βββ server.py # Stateless MCP μ§μ μ β βββ hwpx_ops.py # κ³ κΈ/λ΄λΆ μ°μ° λνΌ β βββ core/ # λ¬Έλ¨/ν/κ²μ/μμ ν΅μ¬ λ‘μ§ β βββ tools.py # νμ₯ λꡬ μ€ν€λ§/μ μ β βββ schema/ # JSON μ€ν€λ§ λΉλ/μ 리기 βββ tests/ # λ¨μ + E2E + νκ· ν μ€νΈ βββ pyproject.toml ``` <br> ## Comparison | | hwpx-mcp-server | hwp(λ°μ΄λ리) COM μλν κ³μ΄ | |---|---|---| | λμ ν¬λ§· | `.hwpx` (Open XML) | `.hwp` (λ°μ΄λ리) μ€μ¬ | | OS | Windows Β· macOS Β· Linux | λμ²΄λ‘ Windows μ€μ¬ | | νκΈ νλ‘κ·Έλ¨ μμ‘΄ | λΆνμ | νμν κ²½μ°κ° λ§μ | | μ°λ λ°©μ | MCP + νμ΄μ¬ λΌμ΄λΈλ¬λ¦¬ | λ°μ€ν¬ν± μ± μλν | <br> ## Contributing κΈ°μ¬λ₯Ό νμν©λλ€. 1. Fork ν λΈλμΉ μμ± 2. λ³κ²½ + ν μ€νΈ μΆκ°/μμ 3. `pytest -q` ν΅κ³Ό νμΈ ν PR <br> ## License [MIT](LICENSE) Β© κ³ κ·ν (Kyuhyun Koh) <br> ## Author **κ³ κ·ν** β κ΄κ΅κ³ λ±νκ΅ μ 보·컴ν¨ν° κ΅μ¬ - βοΈ [kokyuhyun@hotmail.com](mailto:kokyuhyun@hotmail.com) - π [@airmang](https://github.com/airmang)
Composite of vulnerability cleanliness, spec conformance, provenance, stability, and usage signals β scanned and weighted by Cognium. Human and agent signals are tracked separately. Last scanned 2026-09-28.
Scan details: Circle-IR · 2026-09-28 · Appeal
View full trust & usage report βMetadata
- Version
- 1.0.0
- Skill type
- atomic
- Execution layer
- container
- Category
- version-control
- Source
- Smithery
- Repository
- github.com/airmang/hwpx-mcp-server
- Author type
- human
- Last scanned
- 2026-09-28
- Updated
- 2026-09-28
Use via MCP
Resolve νκΈ mcp hwpx MCP Server from your agent
Streamable HTTP transport at https://api.skillsregistry.net/mcp. No auth for read tools. Discovery: .well-known/mcp.json.
One command in your shell β Claude Code wires it up and verifies the connection. Run /mcp in any session to confirm.
claude mcp add --transport http --scope user skillsregistry https://api.skillsregistry.net/mcp --scope user for --scope project to commit it to .mcp.json.