Skip to content

feat: OnlyOffice office MCP tools (edit/generate/convert/export) + attachment images - EXO-88456#342

Open
bmestrallet wants to merge 5 commits into
feature/ai-contributionfrom
feat/onlyoffice-mcp-tools-EXO-88354
Open

feat: OnlyOffice office MCP tools (edit/generate/convert/export) + attachment images - EXO-88456#342
bmestrallet wants to merge 5 commits into
feature/ai-contributionfrom
feat/onlyoffice-mcp-tools-EXO-88354

Conversation

@bmestrallet

Copy link
Copy Markdown

What

Adds OnlyOffice office-document MCP tools for the EVA AI agent, driven by the OnlyOffice Document Builder:

  • edit_document, edit_spreadsheet, edit_presentation (create or modify), generate_document (from template), convert_document, export_document_as_pdf, get_document_editor_link
  • A Spring bridge (OnlyofficeApplication) so the kernel-only add-on exposes the @Service ... McpToolPlugin beans, plus ai-tool-definitions.json.

Fixes folded in

  • xlsx → PDF: re-activate the primary data sheet before save (the DS exports only the active sheet, which add_sheet left blank).
  • pptx create: explicit black text fill (shapes default to the light-1/white theme colour → invisible) and reuse of the default slide 0 (no leading blank slide).
  • modify reliability: bind a SessionProvider when the thread has none (fixes the DocumentUpdateActivityListener NPE); checkout before createVersion; evict the cached editor Config after the write so a reopen shows the new content.
  • Api.CreateTable argument order.

EVA chat-attachment images

edit_presentation/edit_document declare top-level attachment_object_type/attachment_object_id (EVA injects these for an image-capable tool); add_image ops without an explicit url/document_id embed the attached image, resolved via the shared UploadToolUtils.resolveImage (ACL-enforced as the user).

Dependency / CI

Depends on mcp-server #13 (UploadToolUtils, EXO-88348) — this branch's pom consumes mcp-server-tools:*-ai-contribution-SNAPSHOT. CI will be red until #13 merges and a consuming version is published.

Known follow-up

Refining the attachment path: fall back to the chat attachment when a model-invented url fails to resolve, and tighten the editor-cache invalidation for the attachment-modify case.

Board: EXO-88354.

🤖 Generated with Claude Code

bmestrallet and others added 5 commits July 7, 2026 22:56
…-88354

Add the security-critical shared service primitive used by the office MCP
tools to CREATE and MODIFY native docx/xlsx/pptx via the ONLYOFFICE Document
Builder:

- runDocBuilderScript(scriptBody, assets, outputFormat, outputName, userId):
  stages the script + referenced assets in an in-memory, single-use, expiring
  registry and serves them to the Document Server through the EXISTING
  host-restricted (canDownloadBy) and JWT-guarded (validateToken)
  /onlyoffice/editor/content/{userId}/{key} endpoint, at URLs built from
  exo.base.url. The DS auto-signs the script fetch (Authorization header);
  in-script asset URLs carry a signed ?token= query param. Maps error codes to
  LLM-directed IllegalStateException.
- saveNewVersion: writes Builder output back onto an existing node (MODIFY).
- getContent short-circuits to the staged-asset registry (single-use).
- content REST endpoint accepts the token via ?token= query param.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>


Replace create_office_document with a symmetric family of operations-based
office tools that both CREATE (no document_id) and MODIFY (document_id given,
saved as a new version) native office files via the ONLYOFFICE Document
Builder, plus template-fill and conversion:

- edit_spreadsheet (xlsx): set_cells, set_formula, add_chart, add_sheet
- edit_presentation (pptx): add_slide, set_slide, add_image
- edit_document (docx): add_heading, add_paragraph, add_table, add_image,
  replace_text, and a single set_html (routed to the HTML->docx conversion
  API, preserving the former create_office_document capability)
- generate_document: template + {{placeholder}} search/replace merge
- convert_document: format -> format via convertNodeContent
- kept: export_document_as_pdf, get_document_editor_link

Each edit_* tool builds a lean, format-specific Document Builder script
(CreateFile or OpenFile -> apply operations -> SaveFile), gathers assets
(existing file, images resolved from a URL via the SSRF-guarded UploadToolUtils
or a DMS document_id), runs the shared runDocBuilderScript primitive, and
stores a new file or a new version. The nested operations array is accepted as
a JSON string (parsed server-side) because the MCP binder does not reliably
bind nested arrays. All acts as the current user (ACL enforced via a user JCR
session). ai-tool-definitions.json updated (create_office_document removed);
-parameters flag and **/*.json resource include kept.

19 Mockito unit tests cover create/modify/failed-build/validation and the
generated script for every tool.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lder generator - EXO-88354

The add_table generator emitted Api.CreateTable(colCount, rowCount) but the
Document Server's Api.CreateTable is (nRows, nCols). A table with N rows was
built with too few rows, so GetRow(r) for later rows threw a Row-index-out-of-
bounds error (docbuilder ExitCode error:-80). Swapped to CreateTable(rowCount,
colCount), verified against a live Document Server docbuilder endpoint.

Validated every generator operation (spreadsheet set_cells/set_formula/
add_chart/add_sheet, presentation add_slide/set_slide/add_image, document
add_heading/add_paragraph/add_table/add_image/replace_text, and the CreateFile
vs OpenFile paths) against the live DS: all produce valid OOXML with the
expected content. add_table was the only bug.

Added golden-string regression tests pinning the exact emitted Document Builder
script (add_table rows-first + last-cell addressing, set_cells GetRangeByNumber
row/col order, add_chart 10-arg signature, add_slide, and the OpenFile modify
path), with a class note that true API-correctness requires the manual DS check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ability) - EXO-88354

- edit_spreadsheet: re-activate the primary data sheet before save so
  xlsx->PDF export renders it (DS exports only the active sheet).
- edit_presentation: set explicit black text fill (shapes default to the
  light-1/white theme colour) and reuse the default slide 0 on create so
  slides show their text and there is no leading blank slide.
- saveNewVersion (MCP modify): bind a SessionProvider when the thread has
  none (fixes the DocumentUpdateActivityListener NPE), and evict the cached
  editor Config after the write so reopening shows the new content, not a
  stale DS-cached copy. checkout before createVersion so current advances.
- ai-tool-definitions.json: rename edit_* folder param to parent_folder_id.
- Add saveNewVersion regression tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cument add_image - EXO-88354

EVA forwards a chat-attached image by injecting the top-level string params
attachment_object_type + attachment_object_id into any tool that declares both
in its schema. Since the office tools carry images inside the opaque operations
JSON string (which EVA cannot reach into), declare those two params at the tool
level on edit_presentation and edit_document; the server applies the attachment
to add_image ops that lack an explicit url/document_id.

- OnlyofficeMcpTool: inject AttachmentService + FileService; add tool-level
  attachmentObjectType/attachmentObjectId, plumb through runEdit ->
  appendPresentationOps/appendDocumentOps -> resolveImageBytes. Resolution
  precedence: op url -> op document_id -> per-op attachment_object_* ->
  tool-level attachment_object_*. Attachment bytes resolved via the shared
  UploadToolUtils.resolveImage, ACL-enforced as the current user.
- ai-tool-definitions.json: declare the two params on edit_presentation/
  edit_document so EVA auto-fills them; edit_spreadsheet unchanged (no image op).

Verified against the live Document Server: the attached PNG embeds byte-identical
into ppt/media and word/media and renders in the exported PDF.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bmestrallet bmestrallet requested a review from ahamdi July 8, 2026 14:33
@bmestrallet bmestrallet changed the title feat: OnlyOffice office MCP tools (edit/generate/convert/export) + attachment images - EXO-88354 feat: OnlyOffice office MCP tools (edit/generate/convert/export) + attachment images - EXO-88456 Jul 8, 2026
@exo-swf exo-swf force-pushed the feature/ai-contribution branch from 3dfad0e to c33dd1f Compare July 11, 2026 01:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant