Content
# report-mcp
A [Model Context Protocol](https://modelcontextprotocol.io/) server that fills user-uploaded document templates (DOCX / HWP / HWPX / PDF) with chatbot-generated content, preserving the original formatting, tables, and images.
- **Input**: User-attached empty template file + chatbot response
- **Output**: Report file with preserved template design (DOCX→DOCX, HWP/HWPX→HWPX)
- **Core Value**: Modifies the original IR without regeneration, preserving font size, color, tables, images, and page layout.
## Operation Flow
```
User-attached template.hwpx Chatbot-generated response text
↓ ↓
describe / inspect ←──→ Gather information on TOC, cells, and length limits
list_template_targets
↓ ↓
edits list (target_id, new_text)
↓
fill_and_save → result.hwpx (preserves original formatting, replaces content only)
```
## Exposed Tools (7)
| Tool | Purpose |
|---|---|
| `register_template(template_b64, template_filename)` | Caches a template on the server and returns a `template_id`. Avoids re-uploading base64 for multiple tool calls with the same file. |
| `unregister_template(template_id)` | Releases cache (automatically expires in 1 hour) |
| `describe_template(...)` | Provides a summary — format, page and image count, top-level paragraphs |
| `inspect_template(..., start, limit)` | Paginated paragraph view |
| `list_template_targets(..., target_kinds, start, limit)` | Lists all editable locations + target_id + text_hash + length information |
| `fill_and_save(..., edits, ...)` | Validation → filtering → application → saving |
| `convert_to_hwpx(...)` | Converts HWP/HWPX/HWTX to HWPX (without editing) |
## Input/Output Modes (File System Isolation)
All tools accept templates in **two ways**:
- **`template_path`** — file path on the server machine (e.g., `C:/Users/.../template.hwpx`). Fast and no copying required.
- **`template_b64` + `template_filename`** — base64-encoded original bytes + original file name (e.g., `template_b64="UEsDBBQ...", template_filename="template.hwpx"`). Used when the chatbot session and MCP server are on different file systems (e.g., Anthropic sandbox ↔ user Windows).
`fill_and_save` also supports:
- **`output_path`** — saves the result file on the server machine
- **`return_output_bytes=True`** — includes `output_b64` (base64 bytes) + `output_size_bytes` in the response. Allows the chatbot to directly deliver the result to the user.
### Example Invocation from Chatbot Session (Sandbox)
```python
import base64
file_bytes = open("template.hwpx", "rb").read()
b64 = base64.b64encode(file_bytes).decode("ascii")
# 1. Analyze template
desc = describe_template(template_b64=b64, template_filename="template.hwpx")
# 2. List editable locations
targets = list_template_targets(template_b64=b64, template_filename="template.hwpx")
# 3. Construct and apply edits
result = fill_and_save(
template_b64=b64,
template_filename="template.hwpx",
edits=[...],
return_output_bytes=True,
)
output_bytes = base64.b64decode(result["output_b64"])
# Deliver output_bytes as an attachment to the user
```
## Installation
### Prerequisites
- **Python 3.13+** (document-processor dependency)
- **JDK 11+** (required for HWP or PDF input. Optional for DOCX and HWPX only)
- **git** (clones document-processor directly)
### Project Installation
```powershell
git clone https://github.com/jaykim429/report-mcp.git
cd report-mcp
py -3.13 -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -e .
```
The document-processor's known `_edited` cumulative bug is automatically patched by `apply_library_patches()` during import. For a more permanent fix, apply [`patches/document_processor_edited_cumulation.patch`](patches/document_processor_edited_cumulation.patch).
## MCP Client Registration
### Claude Code (Per Project)
The `.claude/mcp_servers.json` file is already included. Running Claude Code from this folder will automatically detect it.
### Claude Desktop (Global)
Add to `%APPDATA%\Claude\claude_desktop_config.json`:
```json
{
"mcpServers": {
"report-mcp": {
"command": "C:\\path\\to\\report-mcp\\.venv\\Scripts\\python.exe",
"args": ["-m", "report_mcp"],
"env": { "PYTHONIOENCODING": "utf-8" }
}
}
}
```
Restart Claude Desktop to see the 4 tools in the menu.
## Response Standard
All tools return a dict with the following fields:
```
status : ok / dry_run_ok / 13 other failure states
recovery_hint : hint for the chatbot on what to do next (includes failed target_id and current hash)
```
### Defined Statuses
| status | situation |
|---|---|
| `ok` | successful application |
| `dry_run_ok` | validation only (no file written) |
| `not_found` | template path not found |
| `bad_argument` | incorrect argument (negative start, invalid target_kinds, directory path, etc.) |
| `edit_parse_failed` | edits schema error |
| `duplicate_target_id` | two edits for the same target_id |
| `style_field_target_mismatch` | run property on a paragraph target (or vice versa) |
| `validation_failed` | hash mismatch, etc. (detailed in failed_targets) |
| `output_extension_mismatch` | output extension does not match template format |
| `format_not_writable` | PDF output, etc. |
| `format_requires_java` | Java not installed for PDF/binary HWP input |
| `file_error` / `permission_error` | OS-level file issues |
| `apply_failed` / `runtime_error` | other library exceptions |
## Self-Contained Safeguards (Chatbot Does Not Need to Worry)
1. **Automatic conflict resolution for container/child edits** — determines priority and guides redundant edits to `skipped_redundant_edits`.
2. **Duplicate target_id pre-check** — immediate `duplicate_target_id` response if the chatbot sends two edits to the same location.
3. **Output extension verification** — safe rejection with `output_extension_mismatch` if sent with an incorrect extension (e.g., `.pdf`).
4. **Defensive type handling** — clean handling of `edits=None` / `edits="string"`.
5. **EAW-aware length guardrail** — accurate reflection of length warnings with EAW width calculation.
6. **document-processor `_edited` cumulative bug monkey-patch** — maintained idempotently even after pip reinstallation.
7. **In-place overwrite safety** — safe handling using a temporary file when `template_path == output_path`.
## Project Structure
```
report-mcp/
├── src/report_mcp/
│ ├── server.py FastMCP wiring + 4 tool definitions
│ ├── documents.py TemplateReader class (read API)
│ ├── pipeline.py FillPipeline class (validation → filtering → application)
│ ├── length.py LengthGuardrail class (EAW width calculation)
│ ├── errors.py ExceptionClassifier class
│ ├── responses.py ok/error/not_found factory
│ └── patches.py document-processor monkey-patch
├── tests/ 10 probe/test suites
├── archive/ disposable demo scripts
├── patches/ document-processor patch files
└── .claude/ Claude Code MCP registration settings
```
## Testing
```powershell
.\.venv\Scripts\Activate.ps1
foreach ($f in Get-ChildItem tests\*.py) { python $f.FullName }
```
10 test suites:
- `verify_patch_no_batching.py` — library patch verification (32 edits in a single call)
- `probe_edge_cases.py` — 10 test cases for empty edits, duplicates, unknown targets, in-place overwrites, etc.
- `probe_pdf_input.py` — clean rejection of PDF input without Java
- `probe_round_two/three/four/five.py` — cumulative verification of describe + StructuralEdit + StyleEdit + MCP transport + stdout cleanliness
- `probe_real_defects.py` — regression prevention for 6 essential defects
- `test_mcp_production_ready.py` — server instructions, tool docstrings, batching, cell-conflict gate
- `test_length_guardrail.py` — EAW length warnings
## Known Limitations
- **HWP (binary, .hwp)**: Requires Java 11+. Output is limited to HWPX.
- **PDF**: Input only. Output not supported (library limitation). Recommend saving as DOCX.
- **Image removal**: Currently not supported. No `remove_image` structural edit in the library.
- **Display width heuristic**: `max_recommended_chars` is an EAW-based approximation. Limited accuracy for proportional fonts.
## License / Dependencies
The core functionality of this project depends on [CGINSIDE-ROOKIES/document-processor](https://github.com/CGINSIDE-ROOKIES/document-processor). Requires access to the internal repository.
## Related Documents
- [Model Context Protocol Official](https://modelcontextprotocol.io/)
- [Anthropic FastMCP SDK](https://github.com/modelcontextprotocol/python-sdk)