claude-code-hwp-mcp 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -151,6 +151,9 @@ export function registerAnalysisTools(server, bridge, toolset = 'standard') {
151
151
  // HWPX → XML 직접 검색 시도. EBUSY 시 COM 폴백.
152
152
  if (bridge.getCurrentDocumentFormat() === 'HWPX') {
153
153
  try {
154
+ // COM 메모리 변경사항을 파일에 반영 (XML 엔진이 최신 내용을 읽도록)
155
+ await bridge.ensureRunning();
156
+ await bridge.send('save_document', {});
154
157
  const doc = await readHwpxXml(filePath, 'Contents/section0.xml');
155
158
  const result = searchTextInSection(doc, search);
156
159
  const limited = max_results ? result.results.slice(0, max_results) : result.results.slice(0, 50);
@@ -135,6 +135,9 @@ export function registerEditingTools(server, bridge, toolset = 'standard') {
135
135
  // HWPX → XML 직접 치환 시도 (COM 우회). EBUSY 시 COM 폴백.
136
136
  if (bridge.getCurrentDocumentFormat() === 'HWPX' && !use_regex) {
137
137
  try {
138
+ // COM 메모리 변경사항을 파일에 반영 (XML 엔진이 최신 내용을 읽도록)
139
+ await bridge.ensureRunning();
140
+ await bridge.send('save_document', {});
138
141
  const doc = await readHwpxXml(filePath, 'Contents/section0.xml');
139
142
  const count = replaceTextInSection(doc, find, replace);
140
143
  await writeHwpxXml(filePath, filePath, 'Contents/section0.xml', doc);
@@ -183,6 +186,9 @@ export function registerEditingTools(server, bridge, toolset = 'standard') {
183
186
  // HWPX → XML 직접 다건 치환 시도. EBUSY 시 COM 폴백.
184
187
  if (bridge.getCurrentDocumentFormat() === 'HWPX' && !use_regex) {
185
188
  try {
189
+ // COM 메모리 변경사항을 파일에 반영
190
+ await bridge.ensureRunning();
191
+ await bridge.send('save_document', {});
186
192
  const doc = await readHwpxXml(filePath, 'Contents/section0.xml');
187
193
  const results = [];
188
194
  let totalCount = 0;
@@ -235,6 +241,8 @@ export function registerEditingTools(server, bridge, toolset = 'standard') {
235
241
  // HWPX → XML 직접 조작 시도. EBUSY 시 COM 폴백.
236
242
  if (bridge.getCurrentDocumentFormat() === 'HWPX' && !color) {
237
243
  try {
244
+ await bridge.ensureRunning();
245
+ await bridge.send('save_document', {});
238
246
  const doc = await readHwpxXml(filePath, 'Contents/section0.xml');
239
247
  const found = findAndAppendInSection(doc, find, append_text);
240
248
  if (!found) {
@@ -418,6 +426,8 @@ export function registerEditingTools(server, bridge, toolset = 'standard') {
418
426
  // HWPX → XML 직접 N번째 치환 시도. EBUSY 시 COM 폴백.
419
427
  if (bridge.getCurrentDocumentFormat() === 'HWPX') {
420
428
  try {
429
+ await bridge.ensureRunning();
430
+ await bridge.send('save_document', {});
421
431
  const doc = await readHwpxXml(filePath, 'Contents/section0.xml');
422
432
  const replaced = replaceTextNthInSection(doc, find, replace, nth);
423
433
  if (replaced) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-hwp-mcp",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "MCP server for HWP (한글) document automation via pyhwpx COM API. 94 tools for document editing, analysis, table formatting, and AI-powered filling.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -201,6 +201,12 @@ def dispatch(hwp, method, params):
201
201
  validate_params(params, ["path"], method)
202
202
  save_path = validate_file_path(params["path"], must_exist=False)
203
203
  fmt = params.get("format", "HWP").upper() # pyhwpx는 대문자 포맷 필요 (HWP, HWPX, PDF 등)
204
+ # 내보내기 전 현재 문서 저장 (COM 메모리 → 파일 반영, 빈 PDF 방지)
205
+ if _current_doc_path and fmt in ("PDF", "DOCX", "HTML"):
206
+ try:
207
+ hwp.save()
208
+ except Exception:
209
+ pass
204
210
  hwp.save_as(save_path, fmt)
205
211
  # 파일 실제 생성 확인
206
212
  if not os.path.exists(save_path):
@@ -654,6 +660,21 @@ def dispatch(hwp, method, params):
654
660
  validate_params(params, ["path", "format"], method)
655
661
  save_path = validate_file_path(params["path"], must_exist=False)
656
662
  fmt = params["format"].upper() # HWP, HWPX, PDF, HTML, TXT 등
663
+ # DOCX/HTML은 HWP COM에서 미지원 — 타임아웃 방지
664
+ if fmt in ("DOCX", "DOC"):
665
+ return {"status": "not_supported",
666
+ "message": "DOCX 직접 내보내기는 한/글 COM에서 지원되지 않습니다. PDF로 내보내기를 권장합니다.",
667
+ "alternative": "hwp_export_pdf"}
668
+ if fmt == "HTML":
669
+ return {"status": "not_supported",
670
+ "message": "HTML 직접 내보내기는 한/글 COM에서 지원되지 않습니다. hwp_get_as_markdown으로 마크다운 변환 후 HTML로 변환하세요.",
671
+ "alternative": "hwp_get_as_markdown"}
672
+ # PDF/내보내기 전 현재 문서 저장 (COM 메모리 → 파일 반영, 빈 PDF 방지)
673
+ if _current_doc_path:
674
+ try:
675
+ hwp.save()
676
+ except Exception:
677
+ pass
657
678
  result = hwp.save_as(save_path, fmt)
658
679
  # 파일 실제 생성 확인
659
680
  file_exists = os.path.exists(save_path)
@@ -665,6 +686,12 @@ def dispatch(hwp, method, params):
665
686
  if method == "verify_layout":
666
687
  # PDF로 내보내고 PNG 이미지로 변환 → Claude Code의 Read로 시각적 검증
667
688
  import tempfile
689
+ # 먼저 현재 문서 저장 (COM 메모리 → 파일 반영, 빈 PDF 방지)
690
+ if _current_doc_path:
691
+ try:
692
+ hwp.save()
693
+ except Exception:
694
+ pass
668
695
  tmp_pdf = os.path.join(tempfile.gettempdir(), "hwp_verify_layout.pdf")
669
696
  try:
670
697
  hwp.save_as(tmp_pdf, "PDF")