Class OnlyofficeMcpTool

java.lang.Object
org.exoplatform.onlyoffice.mcp.OnlyofficeMcpTool
All Implemented Interfaces:
io.meeds.mcp.server.plugin.McpToolPlugin

@Service @Profile("mcp-server") public class OnlyofficeMcpTool extends Object implements io.meeds.mcp.server.plugin.McpToolPlugin
MCP tools exposing the ONLYOFFICE editor add-on to the AI agent (EVA). The core is a symmetric family of operations-based office tools that both CREATE (no document_id) and MODIFY (a document_id is given, saved back as a new version) native office files through the ONLYOFFICE Document Server Document Builder:
  • edit_spreadsheet → xlsx
  • edit_presentation → pptx
  • edit_document → docx
plus generate_document (template + search/replace merge), convert_document (format→format), export_document_as_pdf and get_document_editor_link.

Every method acts as the current user: source / target JCR nodes are resolved through a user SessionProvider (built from the user's ACL identity), so document ACLs are enforced. The Document Builder script and its assets are run through the shared, security-critical OnlyofficeEditorService.runDocBuilderScript(java.lang.String, java.util.Map<java.lang.String, byte[]>, java.lang.String, java.lang.String, java.lang.String) primitive (see its javadoc for the trust model). A null/empty Document Server result is always translated into an LLM-directed IllegalStateException.

operations argument. The nested operations array is accepted as a JSON string (a JSON array of {"type":...} objects) because the MCP argument binder does not reliably bind a nested array; it is parsed server-side.

  • Field Details

    • FILE_URL_FORMAT

      public static final String FILE_URL_FORMAT
      In-app preview URL of a stored file (same shape as the Documents add-on).
      See Also:
  • Constructor Details

    • OnlyofficeMcpTool

      public OnlyofficeMcpTool(OnlyofficeEditorService onlyofficeEditorService, org.exoplatform.documents.service.DocumentFileService documentFileService, org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.portal.config.UserACL userAcl, org.exoplatform.services.jcr.RepositoryService repositoryService, org.exoplatform.upload.UploadService uploadService, org.exoplatform.social.attachment.AttachmentService attachmentService, org.exoplatform.commons.file.services.FileService fileService)
  • Method Details

    • editSpreadsheet

      public OfficeDocumentModel editSpreadsheet(String documentId, String parentFolderId, String name, String operations) throws IllegalAccessException, org.exoplatform.commons.exception.ObjectNotFoundException
      Creates or modifies a spreadsheet (xlsx). Pass document_id to MODIFY an existing spreadsheet (saved back as a new version), or parent_folder_id and name to CREATE a new one. The operations are applied via the ONLYOFFICE Document Builder.

      Supported operations (a JSON array string):

      • {"type":"set_cells","start":"A1","values":[["Region","Sales"],["North",120]]}
      • {"type":"set_formula","cell":"B4","formula":"=SUM(B2:B3)"}
      • {"type":"add_chart","chart":"bar|line|pie","range":"Sheet1!$A$1:$B$3","title":"..."}
      • {"type":"add_sheet","name":"Q3"} (subsequent ops target the new sheet)
      Parameters:
      documentId - optional JCR uuid of an existing spreadsheet to modify
      parentFolderId - folder id where a new spreadsheet is created (create mode)
      name - new spreadsheet name WITHOUT extension (create mode)
      operations - a JSON array string of spreadsheet operations
      Returns:
      the created / modified document (id + name)
      Throws:
      IllegalAccessException
      org.exoplatform.commons.exception.ObjectNotFoundException
    • editPresentation

      public OfficeDocumentModel editPresentation(String documentId, String parentFolderId, String name, String operations, String attachmentObjectType, String attachmentObjectId) throws IllegalAccessException, org.exoplatform.commons.exception.ObjectNotFoundException
      Creates or modifies a presentation (pptx). Pass document_id to MODIFY (saved back as a new version) or parent_folder_id + name to CREATE.

      Supported operations (a JSON array string):

      • {"type":"add_slide","layout":"title|content|closing","title":"...","bullets":["a","b"]}
      • {"type":"set_slide","index":0,"title":"...","bullets":[...]} (replaces the slide content)
      • {"type":"add_image","slide":1,"url":"https://.../pic.png"} or {"type":"add_image","slide":1,"document_id":"<uuid>"}

      When the user attaches an image in the EVA chat, the agent injects the chat-attachment reference into the top-level attachmentObjectType / attachmentObjectId parameters; any add_image operation that has neither url nor document_id then resolves its bytes from that attachment (see resolveImageBytes(org.json.JSONObject, javax.jcr.Session, java.lang.String, java.lang.String)).

      Parameters:
      documentId - optional JCR uuid of an existing presentation to modify
      parentFolderId - folder id where a new presentation is created (create mode)
      name - new presentation name WITHOUT extension (create mode)
      operations - a JSON array string of presentation operations
      attachmentObjectType - object type of the EVA chat-attachment image source (auto-filled by the agent)
      attachmentObjectId - object id of the EVA chat-attachment image source (auto-filled by the agent)
      Returns:
      the created / modified document (id + name)
      Throws:
      IllegalAccessException
      org.exoplatform.commons.exception.ObjectNotFoundException
    • editDocument

      public OfficeDocumentModel editDocument(String documentId, String parentFolderId, String name, String operations, String attachmentObjectType, String attachmentObjectId) throws IllegalAccessException, org.exoplatform.commons.exception.ObjectNotFoundException
      Creates or modifies a text document (docx). Pass document_id to MODIFY (saved back as a new version) or parent_folder_id + name to CREATE.

      Supported operations (a JSON array string):

      • {"type":"add_heading","level":1,"text":"..."}
      • {"type":"add_paragraph","text":"...","bold":false,"italic":false}
      • {"type":"add_table","rows":[["A","B"],["1","2"]]}
      • {"type":"add_image","url":"https://.../pic.png"} or {"type":"add_image","document_id":"<uuid>"}
      • {"type":"replace_text","search":"{{name}}","replace":"ACME"}
      • {"type":"set_html","html":"<h1>..</h1>"} (CREATE only, must be the only operation; authored via the HTML conversion path, not the Builder)

      When the user attaches an image in the EVA chat, the agent injects the chat-attachment reference into the top-level attachmentObjectType / attachmentObjectId parameters; any add_image operation that has neither url nor document_id then resolves its bytes from that attachment (see resolveImageBytes(org.json.JSONObject, javax.jcr.Session, java.lang.String, java.lang.String)).

      Parameters:
      documentId - optional JCR uuid of an existing document to modify
      parentFolderId - folder id where a new document is created (create mode)
      name - new document name WITHOUT extension (create mode)
      operations - a JSON array string of document operations
      attachmentObjectType - object type of the EVA chat-attachment image source (auto-filled by the agent)
      attachmentObjectId - object id of the EVA chat-attachment image source (auto-filled by the agent)
      Returns:
      the created / modified document (id + name)
      Throws:
      IllegalAccessException
      org.exoplatform.commons.exception.ObjectNotFoundException
    • generateDocument

      public OfficeDocumentModel generateDocument(String templateDocumentId, String folderId, String name, String data) throws IllegalAccessException, org.exoplatform.commons.exception.ObjectNotFoundException
      Generates a new document from a template by replacing every placeholder with its value (a search/replace merge run through the Document Builder). Unlike edit_document's replace_text (which edits a document in place for one-off substitutions), this is the template-fill workflow: it always CREATES a new file from a template document and takes the whole placeholder map at once.
      Parameters:
      templateDocumentId - the JCR uuid of the template document (e.g. a docx with {{client}} placeholders)
      folderId - optional destination folder; defaults to the template's folder
      name - the produced document name WITHOUT extension; defaults to the template name
      data - a JSON object string mapping each placeholder to its replacement, e.g. {"{{client}}":"ACME","{{amount}}":"42,000 EUR"}
      Returns:
      the generated document (id + name)
      Throws:
      IllegalAccessException
      org.exoplatform.commons.exception.ObjectNotFoundException
    • convertDocument

      public OfficeDocumentModel convertDocument(String documentId, String targetFormat, String folderId) throws IllegalAccessException, org.exoplatform.commons.exception.ObjectNotFoundException
      Converts an existing office document to another format using the ONLYOFFICE Document Server, storing the result as <originalName>.<target_format>.
      Parameters:
      documentId - the JCR uuid of the source document
      targetFormat - the produced format, e.g. docx, xlsx, pptx, odt, pdf, csv
      folderId - optional destination folder; defaults to the source folder
      Returns:
      the created document (id + name)
      Throws:
      IllegalAccessException
      org.exoplatform.commons.exception.ObjectNotFoundException
    • exportDocumentAsPdf

      public OfficeDocumentModel exportDocumentAsPdf(String documentId, String parentFolderId) throws IllegalAccessException, org.exoplatform.commons.exception.ObjectNotFoundException
      Exports an existing office document as a PDF, stored as <name>.pdf.
      Parameters:
      documentId - the JCR uuid of the source document
      parentFolderId - optional destination folder; defaults to the source folder
      Returns:
      the created PDF document (id + name)
      Throws:
      IllegalAccessException
      org.exoplatform.commons.exception.ObjectNotFoundException
    • getDocumentEditorLink

      public OfficeEditorLinkModel getDocumentEditorLink(String documentId) throws IllegalAccessException, org.exoplatform.commons.exception.ObjectNotFoundException
      Returns the ONLYOFFICE online editor URL of a document, so it can be opened for editing. The user must have edit permission on the document.
      Parameters:
      documentId - the JCR uuid of the document
      Returns:
      the document id, name and editor URL
      Throws:
      IllegalAccessException
      org.exoplatform.commons.exception.ObjectNotFoundException
    • openUserSession

      protected OnlyofficeMcpTool.UserSession openUserSession()
    • materializeUpload

      protected String materializeUpload(byte[] zipBytes, String zipName)
    • releaseUpload

      protected void releaseUpload(String uploadId)