AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified Apache-2.0 Self-run

HwpForge

mcp-ai-screams-hwpforge ยท by ai-screams

Rust library for programmatic control of Korean HWPX documents โ€” Markdownโ†’HWPX conversion, JSON round-trip editing, MCP server for AI agents ๐Ÿ”ฅ

โ€” No reviews yet
0 installs
7 views
0.0% viewโ†’install

Install

$ agentstack add mcp-ai-screams-hwpforge

โœ“ scanned ยท โœ“ verified, works with Claude Code, Cursor, and more.

Security review

โœ“ Passed

No issues found. Passed automated security review. ยท v0.1.0 How review works โ†’

  • โœ“ Prompt-injection patterns
  • โœ“ Secret / credential exfiltration
  • โœ“ Dangerous shell & filesystem operations
  • โœ“ Untrusted network calls
  • โœ“ Known-malicious package signatures

What it can access

  • โœ“ Network access No
  • โœ“ Filesystem access No
  • โœ“ Shell / process execution No
  • โœ“ Environment & secrets No
  • โœ“ Dynamic code execution No

From automated source analysis of v0.1.0. โ€œUsedโ€ means the capability is present in the source โ€” more access means more to trust, not that itโ€™s unsafe.

View the full security report โ†’

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-ai-screams-hwpforge)

Reliability & compatibility

โœ“ Security review passed
0 installs to date
โ€” no reviews yet
โ— 1mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work โ†’
Are you the author of HwpForge? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

HwpForge ๐Ÿ”ฅ

> Rust๋กœ ํ•œ๊ธ€(HWP/HWPX) ๋ฌธ์„œ๋ฅผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ์ œ์–ด > > Hancom ํ•œ๊ธ€ ํŒŒ์ผ ์ฝ๊ธฐ, ์“ฐ๊ธฐ, ๋ณ€ํ™˜


HwpForge๋ž€?

HwpForge๋Š” HWPX ๋ฌธ์„œ(ZIP + XML, KS X 6101)๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ ์˜คํ”ˆ์†Œ์Šค ์ˆœ์ˆ˜ Rust ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ํ•œ๊ตญ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ์›Œ๋“œํ”„๋กœ์„ธ์„œ์ธ Hancom ํ•œ๊ธ€์˜ ์ตœ์‹  ํฌ๋งท์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

์ง€์› ๋ฒ„์ „

| ํ•œ๊ธ€ ๋ฒ„์ „ | ํฌ๋งท | ์ฝ๊ธฐ | ์“ฐ๊ธฐ | ์Šคํƒ€์ผ ์„ธํŠธ | | ----------------- | ------------ | ---- | ---- | ------------------------------ | | ํ•œ๊ธ€ 2014 \~ 2020 | HWPX (.hwpx) | โœ… | โœ… | Classic (18 styles) | | ํ•œ๊ธ€ 2022 \~ 2024 | HWPX (.hwpx) | โœ… | โœ… | Modern (22 styles, ๊ธฐ๋ณธ๊ฐ’) | | ํ•œ๊ธ€ 2025+ | HWPX (.hwpx) | โœ… | โœ… | Latest (23 styles) | | ํ•œ๊ธ€ 97 \~ 2010 | HWP5 (.hwp) | โœ… | โ€” | โ€” |

  • HWPX: OWPML ๊ตญ๊ฐ€ํ‘œ์ค€ (KS X 6101) ๊ธฐ๋ฐ˜, ZIP + XML ์ปจํ…Œ์ด๋„ˆ
  • HWP5: ๊ตฌํ˜• ๋ฐ”์ด๋„ˆ๋ฆฌ ํฌ๋งท. ํ˜„์žฌ๋Š” CLI ์ค‘์‹ฌ์˜ ์ฝ๊ธฐ/์ ๊ฒ€/์žฌ์ถœ๋ ฅ ๊ฒฝ๋กœ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค (convert-hwp5, audit-hwp5, census-hwp5)
  • ์Šคํƒ€์ผ ์„ธํŠธ๋Š” HancomStyleSet enum์œผ๋กœ ์„ ํƒ ๊ฐ€๋Šฅ (๊ธฐ๋ณธ: Modern)

LLM-first ์„ค๊ณ„ ๐Ÿ”ฅ โ€” AI ์นœํ™”์ ์ธ Markdown๊ณผ ๊ณต์‹ ํ•œ๊ธ€ ๋ฌธ์„œ ํฌ๋งท(HWPX), ๋‘ ์„ธ๊ณ„๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ž‡์Šต๋‹ˆ๋‹ค. LLM์ด Markdown์œผ๋กœ ์ž‘์„ฑํ•œ ๋‚ด์šฉ์€ ๊ณต๋ฌธ์„œ ๊ทœ๊ฒฉ์˜ HWPX๋กœ ์ปดํŒŒ์ผ๋˜๊ณ  ๐Ÿ“œ, ๋ฐ˜๋Œ€๋กœ ๊ธฐ์กด HWPX ๋ฌธ์„œ๋Š” AI๊ฐ€ ์‰ฝ๊ฒŒ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋กœ ๊บผ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค โš’๏ธ.

  • ๐Ÿ“„  [HWPX ์™„์ „ ๊ฐ€์ด๋“œ ๋‹ค์šด๋กœ๋“œ](examples/showcase/guides/hwpxcompleteguide/hwpxcompleteguide.hwpx) โ€” HwpForge API๋กœ ์ƒ์„ฑํ•œ 4์„น์…˜ ๋ฐ๋ชจ ๋ฌธ์„œ (ํ•œ๊ธ€์—์„œ ์—ด์–ด๋ณด์„ธ์š”)
  • HWPX Reader for AI โ€” ๊ธฐ์กด ํ•œ๊ธ€ ๋ฌธ์„œ(.hwpx)๋ฅผ Markdown์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ LLM์ด ์ฆ‰์‹œ ์ดํ•ด ๊ฐ€๋Šฅ
  • Full HWPX codec โ€” HWPX ํŒŒ์ผ์„ ์†์‹ค ์—†์ด ๋””์ฝ”๋”ฉ/์ธ์ฝ”๋”ฉ (lossless roundtrip)
  • Markdown bridge โ€” GFM Markdown๊ณผ HWPX ๊ฐ„ ์–‘๋ฐฉํ–ฅ ๋ณ€ํ™˜ (์ฝ๊ธฐ + ์“ฐ๊ธฐ)
  • YAML style template โ€” Figma Design Token์ฒ˜๋Ÿผ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์Šคํƒ€์ผ ์ •์˜ (ํฐํŠธ, ํฌ๊ธฐ, ์ƒ‰์ƒ)
  • Type-safe API โ€” branded index, typestate validation, zero unsafe code

๋น ๋ฅธ ์‹œ์ž‘

์„ค์น˜

# Cargo.toml์— ์ถ”๊ฐ€
cargo add hwpforge

# Markdown ์ง€์› ํฌํ•จ
cargo add hwpforge --features full

๋˜๋Š” Cargo.toml์— ์ง์ ‘ ์ถ”๊ฐ€:

[dependencies]
hwpforge = "0.7"

๐Ÿ”จ Hammer โ€” CLI๋กœ ์‹œ์ž‘ํ•˜๊ธฐ

CLI ๋„๊ตฌ hwpforge(Hammer)๋ฅผ ์„ค์น˜ํ•˜๋ฉด ํ„ฐ๋ฏธ๋„์—์„œ ๋ฐ”๋กœ ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

cargo install hwpforge-bindings-cli
# Markdown โ†’ HWPX ๋ณ€ํ™˜
hwpforge convert report.md -o report.hwpx

# HWPX ๊ตฌ์กฐ ํ™•์ธ
hwpforge inspect report.hwpx

# HWPX โ†’ Markdown ๋ณ€ํ™˜ (AI๊ฐ€ ํ•œ๊ธ€ ๋ฌธ์„œ ์ฝ๊ธฐ)
hwpforge to-md report.hwpx -o report.md

# HWPX โ†’ JSON ์ถ”์ถœ (AI ํŽธ์ง‘์šฉ)
hwpforge to-json report.hwpx --section 0 > section0.json

# JSON โ†’ HWPX ์ง์ ‘ ์ƒ์„ฑ
hwpforge from-json section0.json -o new.hwpx

# JSON์œผ๋กœ ์„น์…˜ ๊ต์ฒด
hwpforge patch report.hwpx --section 0  **AI-first ์„ค๊ณ„**: CLI๋Š” AI agent(Claude Code ๋“ฑ)๊ฐ€ ์ฃผ ์‚ฌ์šฉ์ž์ž…๋‹ˆ๋‹ค.
> Markdown์œผ๋กœ ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ•œ ๋’ค, JSON round-trip์œผ๋กœ ๊ธฐ์กด ์Šคํƒ€์ผ์„ ๋ณด์กดํ•˜๋ฉด์„œ
> section ๋‹จ์œ„๋กœ ์ •๋ฐ€ํ•˜๊ฒŒ ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. `--json` ํ”Œ๋ž˜๊ทธ๋กœ ๋ชจ๋“  ๋ช…๋ น์–ด๊ฐ€
> machine-readable ์ถœ๋ ฅ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

### โš™๏ธ Anvil โ€” MCP Server (Beta)๋กœ AI๊ฐ€ ์ง์ ‘ ํ•œ๊ธ€ ๋ฌธ์„œ๋ฅผ ๋‹ค๋ฃจ๋‹ค

Claude Code, Codex CLI, Claude, ChatGPT, Cursor, Antigravity ๋“ฑ [MCP](https://modelcontextprotocol.io/) ์ง€์› AI ๋„๊ตฌ์—์„œ **ํ•œ๊ธ€ ๋ฌธ์„œ๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•˜๊ณ  ํŽธ์ง‘**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ MCP surface๋Š” **๋ฒ ํƒ€**์ด๋ฉฐ, HWP5 ๊ฒฝ๋กœ๋Š” MCP๊ฐ€ ์•„๋‹ˆ๋ผ CLI workflow๋ฅผ ์šฐ์„ ํ•ฉ๋‹ˆ๋‹ค. "๋ณด๊ณ ์„œ ๋งŒ๋“ค์–ด์ค˜"๋ผ๊ณ  ๋งํ•˜๋ฉด, AI๊ฐ€ ์•Œ์•„์„œ `.hwpx` ํŒŒ์ผ์„ ๋š๋”ฑ ๋งŒ๋“ค์–ด๋ƒ…๋‹ˆ๋‹ค.

#### AI ๋„๊ตฌ์— ๋“ฑ๋ก

ํ•œ ์ค„์ด๋ฉด ์„ค์น˜ + ๋“ฑ๋ก์ด ๋๋‚ฉ๋‹ˆ๋‹ค. npm์€ `npx -y`๊ฐ€ ์ž๋™์œผ๋กœ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

Claude Code (ํ„ฐ๋ฏธ๋„)

npm (๊ถŒ์žฅ โ€” Rust ํˆด์ฒด์ธ ๋ถˆํ•„์š”)

claude mcp add hwpforge -- npx -y @hwpforge/mcp

Cargo (Rust ๊ฐœ๋ฐœ์ž์šฉ)

cargo install hwpforge-bindings-mcp && claude mcp add hwpforge hwpforge-mcp

๋ชจ๋“  ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉ (๊ธ€๋กœ๋ฒŒ)

claude mcp add --global hwpforge -- npx -y @hwpforge/mcp


Codex CLI (ํ„ฐ๋ฏธ๋„)

`~/.codex/config.toml`์— ์ถ”๊ฐ€:

[mcp_servers.hwpforge] command = "npx" args = ["-y", "@hwpforge/mcp"]


๋˜๋Š” CLI๋กœ:

codex mcp add hwpforge -- npx -y @hwpforge/mcp


Claude Desktop (์•ฑ)

์„ค์ • ํŒŒ์ผ์„ ํŽธ์ง‘ํ•ฉ๋‹ˆ๋‹ค:

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "hwpforge": {
      "command": "npx",
      "args": ["-y", "@hwpforge/mcp"]
    }
  }
}

ChatGPT Desktop (์•ฑ)

Settings โ†’ Tools โ†’ Add MCP Server์—์„œ:

  • Name: hwpforge
  • Command: npx -y @hwpforge/mcp

๋˜๋Š” ์„ค์ • ํŒŒ์ผ์„ ์ง์ ‘ ํŽธ์ง‘:

{
  "mcpServers": {
    "hwpforge": {
      "command": "npx",
      "args": ["-y", "@hwpforge/mcp"]
    }
  }
}

Cursor (์—๋””ํ„ฐ)

ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์— .cursor/mcp.json ์ƒ์„ฑ:

{
  "mcpServers": {
    "hwpforge": {
      "command": "npx",
      "args": ["-y", "@hwpforge/mcp"]
    }
  }
}

Antigravity (์—๋””ํ„ฐ)

... ๋“œ๋กญ๋‹ค์šด โ†’ MCP Store โ†’ Manage MCP Servers โ†’ View raw config (mcp_config.json)์— ์ถ”๊ฐ€:

{
  "mcpServers": {
    "hwpforge": {
      "command": "npx",
      "args": ["-y", "@hwpforge/mcp"]
    }
  }
}
๋“ฑ๋กํ•˜๋ฉด 9๊ฐœ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

| ๋„๊ตฌ | ํ•˜๋Š” ์ผ | ํ•œ๋งˆ๋”” | | -------------------- | ----------------------- | ------------------------------------ | | hwpforge_convert | Markdown โ†’ HWPX ๋ณ€ํ™˜ | "์ด ๋งˆํฌ๋‹ค์šด์„ ํ•œ๊ธ€ ํŒŒ์ผ๋กœ!" | | hwpforge_inspect | HWPX ๊ตฌ์กฐ ํ™•์ธ | "์ด ๋ฌธ์„œ ๋ญ๊ฐ€ ๋“ค์–ด์žˆ์–ด?" | | hwpforge_to_json | HWPX โ†’ JSON ์ถ”์ถœ | "์ด ์„น์…˜ ๋‚ด์šฉ ์ข€ ๊บผ๋‚ด๋ด" | | hwpforge_patch | JSON์œผ๋กœ ์„น์…˜ ๊ต์ฒด | "์ด ๋ถ€๋ถ„๋งŒ ๋ฐ”๊ฟ”์„œ ๋‹ค์‹œ ์ €์žฅํ•ด" | | hwpforge_templates | ์Šคํƒ€์ผ ํ”„๋ฆฌ์…‹ ์กฐํšŒ | "์–ด๋–ค ํ…œํ”Œ๋ฆฟ ์“ธ ์ˆ˜ ์žˆ์–ด?" | | hwpforge_validate | HWPX ๊ตฌ์กฐ/๋ฌด๊ฒฐ์„ฑ ๊ฒ€์ฆ | "์ด ํŒŒ์ผ ๋ฌธ์ œ ์—†๋Š”์ง€ ํ™•์ธํ•ด" | | hwpforge_restyle | ์Šคํƒ€์ผ ํ”„๋ฆฌ์…‹ ์ผ๊ด„ ์ ์šฉ | "์ด ๋ฌธ์„œ ํฐํŠธ ๋ฐ”๊ฟ”์ค˜" | | hwpforge_from_json | JSON โ†’ HWPX ์ง์ ‘ ์ƒ์„ฑ | "์ด JSON์œผ๋กœ ํ•œ๊ธ€ ํŒŒ์ผ ๋งŒ๋“ค์–ด" | | hwpforge_to_md | HWPX โ†’ Markdown ๋ณ€ํ™˜ | "์ด ํ•œ๊ธ€ ๋ฌธ์„œ๋ฅผ Markdown์œผ๋กœ ๊บผ๋‚ด์ค˜" |

์—…๋ฐ์ดํŠธ / ์‚ญ์ œ

npm์€ npx -y๊ฐ€ ํ•ญ์ƒ ์ตœ์‹  ๋ฒ„์ „์„ ๊ฐ€์ ธ์˜ค๋ฏ€๋กœ ๋ณ„๋„ ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.

# Cargo ์‚ฌ์šฉ์ž๋งŒ ํ•ด๋‹น
cargo install hwpforge-bindings-mcp --force   # ์—…๋ฐ์ดํŠธ
cargo uninstall hwpforge-bindings-mcp          # ์‚ญ์ œ

> ์™œ MCP? CLI(Hammer)๋Š” AI๊ฐ€ bash ๋ช…๋ น์„ ์‹คํ–‰ํ•ด์•ผ ํ•˜์ง€๋งŒ, MCP(Anvil)๋Š” AI๊ฐ€ ๋„ค์ดํ‹ฐ๋ธŒ ๋„๊ตฌ๋กœ > ์ง์ ‘ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ํŒŒ์ผ ๊ฒฝ๋กœ ํŒŒ์‹ฑ๋„, stdout ํ•ด์„๋„ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. > JSON-RPC๋กœ ์š”์ฒญํ•˜๋ฉด ๊ตฌ์กฐํ™”๋œ JSON์œผ๋กœ ์‘๋‹ต โ€” ๊น”๋”ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”จ ๋ฌธ์„œ ์ƒ์„ฑ

use hwpforge::core::{Document, Draft, Paragraph, Run, Section, PageSettings};
use hwpforge::foundation::{CharShapeIndex, ParaShapeIndex};

let mut doc = Document::::new();
doc.add_section(Section::with_paragraphs(
    vec![Paragraph::with_runs(
        vec![Run::text("Hello, ํ•œ๊ธ€!", CharShapeIndex::new(0))],
        ParaShapeIndex::new(0),
    )],
    PageSettings::a4(),
));

โš’๏ธ HWPX๋กœ ์ธ์ฝ”๋”ฉ

use hwpforge::hwpx::{HwpxEncoder, HwpxStyleStore};
use hwpforge::core::ImageStore;

let validated = doc.validate().unwrap();
let style_store = HwpxStyleStore::with_default_fonts("ํ•จ์ดˆ๋กฌ๋ฐ”ํƒ•");
let image_store = ImageStore::new();
let bytes = HwpxEncoder::encode(&validated, &style_store, &image_store).unwrap();
std::fs::write("output.hwpx", &bytes).unwrap();

โš’๏ธ HWPX ๋””์ฝ”๋”ฉ

use hwpforge::hwpx::HwpxDecoder;

let result = HwpxDecoder::decode_file("input.hwpx").unwrap();
println!("์„น์…˜ ์ˆ˜: {}", result.document.sections().len());

โš’๏ธ HWPX โ†’ Markdown ๋ณ€ํ™˜ (AI๊ฐ€ ํ•œ๊ธ€ ๋ฌธ์„œ ์ฝ๊ธฐ)

๐Ÿ“„ ํ•œ๊ธ€ ์›๋ณธ (.hwpx) ๐Ÿ“ Markdown ๋ณ€ํ™˜ ๊ฒฐ๊ณผ

use hwpforge::hwpx::HwpxDecoder;
use hwpforge::md::MdEncoder;

let decoded = HwpxDecoder::decode_file("government_report.hwpx").unwrap();
let validated = decoded.document.validate().unwrap();
let markdown = MdEncoder::encode_lossy(&validated).unwrap();
println!("{}", markdown); // LLM์ด ๋ฐ”๋กœ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” Markdown

๊ธฐ์กด .hwpx ํŒŒ์ผ์„ Markdown์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋ฉด Claude, GPT ๋“ฑ ์–ด๋–ค LLM์ด๋“  ํ•œ๊ธ€ ๊ณต๋ฌธ์„œ๋ฅผ ์ฆ‰์‹œ ์ฝ๊ณ  ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โš’๏ธ Markdown โ†’ HWPX ๋ณ€ํ™˜

use hwpforge::md::MdDecoder;
use hwpforge::hwpx::{HwpxEncoder, HwpxRegistryBridge};

let md_doc = MdDecoder::decode_with_default("# ์ œ๋ชฉ\n\nMarkdown์—์„œ ๋ณ€ํ™˜!").unwrap();
let bridge = HwpxRegistryBridge::from_registry(&md_doc.style_registry).unwrap();
let rebound = bridge.rebind_draft_document(md_doc.document).unwrap();
let validated = rebound.validate().unwrap();
let image_store = hwpforge::core::ImageStore::new();
let bytes = HwpxEncoder::encode(&validated, bridge.style_store(), &image_store).unwrap();

Feature Flags

| Feature | ๊ธฐ๋ณธ๊ฐ’ | ์„ค๋ช… | | ------- | ------ | -------------------- | | hwpx | Yes | HWPX encoder/decoder | | md | โ€” | Markdown โ†” Core ๋ณ€ํ™˜ | | full | โ€” | ๋ชจ๋“  ๊ธฐ๋Šฅ ํฌํ•จ |

# Markdown ์ง€์› ํฌํ•จ
hwpforge = { version = "0.7", features = ["full"] }

๐Ÿ“œ ์ง€์› ์ฝ˜ํ…์ธ 

| ์นดํ…Œ๊ณ ๋ฆฌ | ์š”์†Œ | | ------------- | -------------------------------------------------------------------- | | ํ…์ŠคํŠธ | Run, character shape, paragraph shape, style (22๊ฐœ ํ•œ์ปด ๊ธฐ๋ณธ ์Šคํƒ€์ผ) | | ๊ตฌ์กฐ | Table (์ค‘์ฒฉ), Image (๋ฐ”์ด๋„ˆ๋ฆฌ + ๊ฒฝ๋กœ), TextBox, Caption | | ๋ ˆ์ด์•„์›ƒ | ๋‹ค๋‹จ, ํŽ˜์ด์ง€ ์„ค์ •, ๊ฐ€๋กœ/์„ธ๋กœ ๋ฐฉํ–ฅ, ์ œ๋ณธ ์—ฌ๋ฐฑ, master page | | ๋จธ๋ฆฌ๊ธ€/๋ฐ”๋‹ฅ๊ธ€ | Header, Footer, ์ชฝ๋ฒˆํ˜ธ (autoNum) | | ๊ฐ์ฃผ/๋ฏธ์ฃผ | ๊ฐ์ฃผ, ๋ฏธ์ฃผ | | ๋„ํ˜• | ์„ , ํƒ€์›, ๋‹ค๊ฐํ˜•, ํ˜ธ, ๊ณก์„ , ์—ฐ๊ฒฐ์„  (์ฑ„์›€, ํšŒ์ „, ํ™”์‚ดํ‘œ ์ง€์›) | | ์ˆ˜์‹ | HancomEQN script ํ˜•์‹ | | ์ฐจํŠธ | 18์ข… chart type (OOXML ํ˜ธํ™˜) | | ์ฐธ์กฐ | ์ฑ…๊ฐˆํ”ผ, ์ƒํ˜ธ ์ฐธ์กฐ, ํ•„๋“œ (๋‚ ์งœ/์‹œ๊ฐ„/์š”์•ฝ), ๋ฉ”๋ชจ, ์ƒ‰์ธ | | ๋ง๋ง/๊ฒน์นจ | ๋ง๋ง (dutmal), ๊ธ€์ž ๊ฒน์นจ | | Markdown | GFM decode, lossy + lossless encode, YAML frontmatter |

์•„ํ‚คํ…์ฒ˜

HwpForge๋Š” ๋ ˆ์ด์–ด๋ฅผ ๋‚˜๋ˆ ์„œ ์ƒ๊ฐํ•˜๋Š” ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค.

  • foundation: ๊ณตํ†ต primitive, unit, index, error
  • core: ํฌ๋งท ๋…๋ฆฝ ๋ฌธ์„œ ๋ชจ๋ธ๊ณผ shared semantics
  • blueprint: ์Šคํƒ€์ผ ์ •์˜์™€ ํ…œํ”Œ๋ฆฟ ๊ณ„์ธต
  • smithy-*: ํฌ๋งท๋ณ„ codec๊ณผ bridge (๊ฐ ํฌ๋ ˆ์ดํŠธ๋Š” ๋‹จ์ผ ํฌ๋งท๋งŒ ๋‹ด๋‹น)
  • convert: ํฌ๋งท ๊ฐ„ ๋ณ€ํ™˜ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ (HWP5 โ†’ HWPX, smithy ์œ„์—์„œ ๋‘ ํฌ๋งท์„ ์—ฎ์Œ)
  • bindings-*: CLI / MCP / Python ์ง„์ž…์ 

๋ ˆ์ด์–ด ๊ตฌ์กฐ

%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '14px', 'lineColor': '#BDBDBD'}}}%%
flowchart TB
    F["foundationprimitive typesunits / indices / errors"]:::foundation
    C["coreshared document modellist / tab / paragraph semantics"]:::core
    B["blueprintstyle registrytemplate authoring"]:::blueprint

    SHX["smithy-hwpxHWPX read/write"]:::smithy
    SH5["smithy-hwp5HWP5 read / audit / re-emission path"]:::smithy
    SMD["smithy-mdMarkdown bridge"]:::smithy

    CONV["convertHWP5 โ†’ HWPX orchestrator"]:::convert

    CLI["bindings-cliHammer"]:::binding
    MCP["bindings-mcpAnvil MCP Server"]:::binding
    PY["bindings-pystub"]:::binding

    F --> C
    C --> B
    C --> SHX
    C --> SH5
    C --> SMD
    B --> SHX
    B --> SMD
    C --> CONV
    SHX --> CONV
    SH5 --> CONV
    SHX --> CLI
    SH5 --> CLI
    SMD --> CLI
    CONV --> CLI
    SHX --> MCP
    SMD --> MCP
    SHX --> PY

    classDef file fill:#FFFDE7,stroke:#F9A825,color:#5D4037
    classDef smithy fill:#FFF3E0,stroke:#FB8C00,color:#E65100
    classDef convert fill:#E0F2F1,stroke:#00897B,color:#004D40
    classDef core fill:#E3F2FD,stroke:#42A5F5,color:#0D47A1
    classDef blueprint fill:#F3E5F5,stroke:#AB47BC,color:#4A148C
    classDef foundation fill:#FAFAFA,stroke:#BDBDBD,color:#424242
    classDef binding fill:#E8F5E9,stroke:#43A047,color:#1B5E20

๋ฐ์ดํ„ฐ ํ๋ฆ„

%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '14px', 'lineColor': '#BDBDBD'}}}%%
flowchart LR
    HWP5[".hwp"]:::file --> SH5["smithy-hwp5"]:::smithy
    MD[".md"]:::file --> SMD["smithy-md"]:::smithy
    HWPX[".hwpx"]:::file  SHX["smithy-hwpx"]:::smithy

    SH5 --> CORE["core document"]:::core
    SHX  CORE
    SMD  CORE
    CORE --> SHX

    CONV["convertHWP5โ†’HWPX ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜"]:::convert --> SH5
    CONV --> SHX

    CLI["CLI"]:::binding --> CONV
    CLI --> SH5
    CLI --> SHX
    CLI --> SMD
    MCP["MCP"]:::binding --> SHX
    MCP --> SMD

    classDef file fill:#FFFDE7,stroke:#F9A825,color:#5D4037
    classDef smithy fill:#FFF3E0,stroke:#FB8C00,color:#E65100
    classDef convert fill:#E0F2F1,stroke:#00897B,color:#004D40
    classDef core fill:#E3F2FD,stroke:#42A5F5,color:#0D47A1
    classDef binding fill:#E8F5E9,stroke:#43A047,color:#1B5E20

ํ•ต์‹ฌ ์›์น™: ๊ตฌ์กฐ(Structure)์™€ ์Šคํƒ€์ผ(Style)์„ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค. core๋Š” shared semantics์™€ ์Šคํƒ€์ผ ์ฐธ์กฐ๋ฅผ ๋“ค๊ณ , blueprint๋Š” ์Šคํƒ€์ผ ์ •์˜๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. smithy-* ๊ณ„์ธต์ด ํฌ๋งท surface๋ฅผ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ „์—์„œ ๊ฐ€์žฅ ์ž์ฃผ ์“ฐ๋Š” ๊ฒฝ๋กœ๋Š” ๋‹ค์Œ ์…‹์ž…๋‹ˆ๋‹ค.

  1. Markdown โ†’ HWPX
  2. HWPX โ†’ Markdown / JSON
  3. HWP5 โ†’ HWPX โ†’ audit / inspect

ํ”„๋กœ์ ํŠธ ํ˜„ํ™ฉ

| ์ง€ํ‘œ | ๊ฐ’ | | ---------------------- | ----------------------- | | Tracked Rust src LOC | ~112,977 | | ํ…Œ์ŠคํŠธ | 2,647๊ฐœ (cargo-nextest) | | ์†Œ์Šค ํŒŒ์ผ | 176 .rs | | Crate ์ˆ˜ | 11๊ฐœ | | ์ปค๋ฒ„๋ฆฌ์ง€ | 90%+ | | Clippy ๊ฒฝ๊ณ  | 0 | | Unsafe ์ฝ”๋“œ | 0 |

๊ฐœ๋ฐœ

ํ•„์ˆ˜ ์š”๊ตฌ์‚ฌํ•ญ

  • Rust 1.88+ (MSRV)
  • (๊ถŒ์žฅ) cargo-nextest โ€” ๋ณ‘๋ ฌ ํ…Œ์ŠคํŠธ ์‹คํ–‰
  • (์„ ํƒ) pre-commit โ€” git hook ์ž๋™ํ™”

MSRV ์ •์ฑ…

  • ํ˜„์žฌ MSRV๋Š” Rust 1.88์ž…๋‹ˆ๋‹ค.
  • HwpForge๋Š” stable์—์„œ 4 ๋ฆด๋ฆฌ์Šค ๋’ค์ฒ˜์ง„ ๋ฒ„์ „์„ ๊ธฐ๋ณธ MSRV ์ •์ฑ…์œผ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • Cargo.toml์˜ rust-version์ด ๋‹จ์ผ ์ง„์‹ค์›์ด๋ฉฐ, CI์˜ Verify โ€บ MSRV job์ด ์ด ๊ณ„์•ฝ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
  • MSRV ์ƒํ–ฅ์ด ํ•„์š”ํ•˜๋ฉด PR์—์„œ ์ด์œ ๋ฅผ ๋ช…์‹œํ•˜๊ณ , Cargo.toml, CI, CHANGELOG๋ฅผ ํ•จ๊ป˜ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐœ๋ฐœ์šฉ ๊ธฐ๋ณธ ํˆด์ฒด์ธ์€ ๋” ์ตœ์‹ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜ธํ™˜์„ฑ ํŒ๋‹จ ๊ธฐ์ค€์€ ์ตœ์‹  stable์ด ์•„๋‹ˆ๋ผ MSRV + CI ํ†ต๊ณผ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค.

โš’๏ธ ๋ช…๋ น์–ด

make ci          # fmt + clippy + test + deny + lint (CI์™€ ๋™์ผ)
make test        # cargo nextest run
make clippy      # cargo clippy (๋ชจ๋“  target, ๋ชจ๋“  feature, -D warnings)
make fmt-fix     # rustfmt ์ž๋™ ํฌ๋งท
make doc         # rustdoc ์ƒ์„ฑ (๋ธŒ๋ผ์šฐ์ €์—์„œ ์—ด๋ฆผ)
make cov         # coverage ๋ฆฌํฌํŠธ (90% gate)

> ๋นŒ๋“œ ๊ฐ€์† (์„ ํƒ): sccache๊ฐ€ PATH์— ์žˆ์œผ๋ฉด make ํƒ€๊นƒ์ด ์ž๋™์œผ๋กœ ์ปดํŒŒ์ผ > ์บ์‹œ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(์—†์œผ๋ฉด ๊ทธ๋Œ€๋กœ ๋™์ž‘ โ€” ์•„๋ฌด๊ฒƒ๋„ ๊นจ์ง€์ง€ ์•Š์Œ). ๋ฐ˜๋ณต make ci๊ฐ€ > ํฌ๊ฒŒ ๋นจ๋ผ์ง‘๋‹ˆ๋‹ค. ์„ค์น˜: cargo install sccache ๋˜๋Š” brew install sccache. > (๋ฆด๋ฆฌ์Šค ํŒŒ์ดํ”„๋ผ์ธ release-plz ๋Š” ์˜ํ–ฅ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)

ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

HwpForge/
โ”œโ”€โ”€ crates/
โ”‚   โ”œโ”€โ”€ hwpforge/                 # Umbrella crate (re-exports)
โ”‚   โ”œโ”€โ”€ hwpforge-foundation/      # ๊ธฐ๋ณธ ํƒ€์ž… (HwpUnit, Color, Index)
โ”‚   โ”œโ”€โ”€ hwpforge-core/            # ๋ฌธ์„œ ๋ชจ๋ธ (์Šคํƒ€์ผ ์ฐธ์กฐ๋งŒ)
โ”‚   โ”œโ”€โ”€ hwpforge-blueprint/       # YAML ํ…œํ”Œ๋ฆฟ (Figma ํŒจํ„ด)
โ”‚   โ”œโ”€โ”€ hwpforge-smithy-hwpx/     # HWPX codec (ZIP+XML โ†” Core)
โ”‚   โ”œโ”€โ”€ hwpforge-smithy-md/       # Markdown codec (MD โ†” Core)
โ”‚   โ”œโ”€โ”€ hwpforge-smithy-hwp5/     # HWP5 decode/projection + inspect helpers
โ”‚   โ”œโ”€โ”€ hwpforge-convert/         # ํฌ๋งท ๊ฐ„ ๋ณ€ํ™˜ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ (HWP5 โ†’ HWPX)
โ”‚   โ”œโ”€โ”€ hwpforge-bindings-py/     # Python bindings (stub)
โ”‚   โ”œโ”€โ”€ hwpforge-bindings-cli/    # CLI ๋„๊ตฌ (hwpforge, shipped)
โ”‚   โ””โ”€โ”€ hwpforge-bindings-mcp/    # MCP Server (hwpforge-mcp)
โ”œโ”€โ”€ tests/                        # ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ + golden fixture
โ””โ”€โ”€ examples/                     # curated showcase + interop artifacts
    โ”œโ”€โ”€ showcase/
    โ””โ”€โ”€ interop/

๊ธฐ์—ฌ

๋ฒ„๊ทธ ์ˆ˜์ •, ํฌ๋งท ๋ฆฌ์„œ์น˜, ํ…Œ์ŠคํŠธ ๋ณด๊ฐ•, ๋ฌธ์„œ ๊ฐœ์„  ๋ชจ๋‘ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.

  • ์‹œ์ž‘ ์ „ ๊ฐ€์ด๋“œ: [CONTRIBUTING.md](CONTRIBUTING.md)
  • ํŠนํžˆ ํ™•์ธํ•  ๊ฒƒ: release-plz๊ฐ€ ์“ฐ๋Š” ์ปค๋ฐ‹ prefix (feat, fix, perf, refactor)
  • ํŠนํžˆ ํ™•์ธํ•  ๊ฒƒ: MSRV ์ •์ฑ…๊ณผ dependency/MSRV ์ƒ์Šน ๊ธฐ์ค€
  • ํŠนํžˆ ํ™•์ธํ•  ๊ฒƒ: ๋ฌธ์„œ ๋ณ€๊ฒฝ ์‹œ mdbook build์™€ markdown lint ๊ฒ€์ฆ
  • ํŠนํžˆ ํ™•์ธํ•  ๊ฒƒ: ๋กœ์ปฌ docs toolchain์€ CI์™€ ๊ฐ™์€ pinned ๋ฒ„์ „(mdbook 0.4.52, mdbook-admonish 1.20.0, mdbook-mermaid 0.16.2)์„ ์“ฐ๋Š” ํŽธ์ด ๋‚ซ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ make install-tools
  • ํŠนํžˆ ํ™•์ธํ•  ๊ฒƒ: CI required checks๋ฅผ ๊นจ์ง€ ์•Š๋Š” ๋ฒ”์œ„์—์„œ์˜ ๋ณ€๊ฒฝ ๋ถ„๋ฆฌ

๋กœ๋“œ๋งต

ํ˜„์žฌ ์ƒํƒœ์™€ ๋‹ค์Œ ๋‹จ๊ณ„

  • [x] HWP5 ์ฝ๊ธฐ/์ ๊ฒ€/์žฌ์ถœ๋ ฅ ๊ฒฝ๋กœ โ€” convert-hwp5, audit-hwp5, census-hwp5
  • [ ] HWP5 public API ํ™•๋Œ€ โ€” umbrella crate surface์™€ broader parity ์ •๋ฆฌ
  • [x] MCP ์„œ๋ฒ„ โ€” Claude, Cursor ๋“ฑ AI ๋„๊ตฌ๊ฐ€ tool๋กœ ์ง์ ‘ HWPX ์ƒ์„ฑยท๊ฒ€์ฆยทํŽธ์ง‘ (9๊ฐœ ๋„๊ตฌ + 4 ๋ฆฌ์†Œ์Šค + 3 ํ”„๋กฌํ”„ํŠธ)
  • [x] CLI ๋„๊ตฌ โ€” hwpforge convert doc.md doc.hwpx ํ•œ ์ค„ ๋ณ€ํ™˜ (7๊ฐœ ๋ช…๋ น์–ด)
  • [ ] HWPX ์™„์ „ ์ง€์› โ€” ์–‘์‹ ์ปจํŠธ๋กค, ๋ณ€๊ฒฝ ์ถ”์ , OLE ๊ฐ์ฒด
  • [ ] Python ๋ฐ”์ธ๋”ฉ โ€” pip install hwpforge๋กœ ์„ค์น˜, PyPI ๋ฐฐํฌ

๋ผ์ด์„ ์Šค

๋‹ค์Œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))
  • MIT license ([LICENSE-MIT](LICENSE-MIT))

Acknowledgements

HwpForge๋Š” ๊ฑฐ์ธ๋“ค์˜ ์–ด๊นจ ์œ„์— ์„œ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Hancom โ€” HWPX ํฌ๋งท์˜ ๊ณต๊ฐœ ๋ฌธ์„œ์™€ KS X 6101 (OWPML) ๊ตญ๊ฐ€ ํ‘œ์ค€์ด ์—†์—ˆ๋‹ค๋ฉด ์ด ํ”„๋กœ์ ํŠธ๋Š” ์‹œ์ž‘์กฐ์ฐจ ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ํฌ๋งท์„ ๊ณต๊ฐœํ•ด ์ฃผ์‹  Hancom์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.
  • openhwp โ€” Rust๋กœ HWP/HWPX๋ฅผ ๋‹ค๋ฃจ๋Š” IR ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„์—์„œ ํฐ ์˜๊ฐ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. HwpForge์˜ Core ๋ ˆ์ด์–ด๊ฐ€ ์กด์žฌํ•  ์ˆ˜ ์žˆ์—ˆ๋˜ ๊ฒƒ์€ openhwp์ด ๋จผ์ € ๊ทธ ๊ธธ์„ ๊ฑธ์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • hwpxlib โ€” Java๋กœ ์ž‘์„ฑ๋œ ๊ฐ€์žฅ ์„ฑ์ˆ™ํ•œ HWPX ๊ตฌํ˜„์ฒด์ž…๋‹ˆ๋‹ค. ์ŠคํŽ™๊ณผ ์‹ค์ œ ๋™์ž‘์˜ ์ฐจ์ด๋ฅผ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ๊ฒฐ์ •์ ์ธ ์ฐธ๊ณ ๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • hwp.js โ€” HWP5 ํฌ๋งท์˜ quirks์™€ edge case๋ฅผ ๊ผผ๊ผผํžˆ ๋ฌธ์„œํ™”ํ•œ ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค. ๋ฐ”์ด๋„ˆ๋ฆฌ ํฌ๋งท์˜ ์–ด๋‘์šด ๊ตฌ์„์„ ๋ฐํ˜€ ์ค€ ๋•๋ถ„์— ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ํฌ๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • hwpx-owpml-model โ€” Hancom์ด ์ง์ ‘ ๊ณต๊ฐœํ•œ C++ OWPML ๋ชจ๋ธ ๊ตฌํ˜„์ฒด

โ€ฆ

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source โ€” we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.