Skip to main content
Glama

add_comment

Add comments or threaded replies to DOCX documents by anchoring to specific paragraphs or replying to existing comments for collaborative editing.

Instructions

Add a comment or threaded reply to a document. Provide target_paragraph_id + anchor_text for root comments, or parent_comment_id for replies.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
file_pathYesPath to the DOCX file.
target_paragraph_idNoParagraph ID to anchor the comment to (for root comments).
anchor_textNoText within the paragraph to anchor the comment to. If omitted, anchors to entire paragraph.
parent_comment_idNoParent comment ID for threaded replies.
authorYesComment author name.
textYesComment body text.
initialsNoAuthor initials (defaults to first letter of author name).

Implementation Reference

  • The addComment MCP tool handler, which manages session resolution and calls either session.doc.addCommentReply or session.doc.addComment.
    export async function addComment(
      manager: SessionManager,
      params: {
        file_path?: string;
        target_paragraph_id?: string;
        anchor_text?: string;
        parent_comment_id?: number;
        author: string;
        text: string;
        initials?: string;
      },
    ): Promise<ToolResponse> {
      const resolved = await resolveSessionForTool(manager, params, { toolName: 'add_comment' });
      if (!resolved.ok) return resolved.response;
      const { session, metadata } = resolved;
    
      try {
        // Reply mode: parent_comment_id provided
        if (params.parent_comment_id != null) {
          const result = await session.doc.addCommentReply({
            parentCommentId: params.parent_comment_id,
            author: params.author,
            text: params.text,
            initials: params.initials,
          });
          manager.markEdited(session);
          return ok(mergeSessionResolutionMetadata({
            comment_id: result.commentId,
            parent_comment_id: result.parentCommentId,
            mode: 'reply',
            file_path: manager.normalizePath(session.originalPath),
          }, metadata));
        }
    
        // Root comment mode: target_paragraph_id required
        if (!params.target_paragraph_id) {
          return err(
            'MISSING_PARAMETER',
            'Either target_paragraph_id (for root comments) or parent_comment_id (for replies) is required.',
            'Provide target_paragraph_id + optional anchor_text for root comments, or parent_comment_id for threaded replies.',
          );
        }
    
        const pid = params.target_paragraph_id;
        const pEl = session.doc.getParagraphElementById(pid);
        if (!pEl) {
          return err(
            'ANCHOR_NOT_FOUND',
            `Paragraph ID ${pid} not found in document`,
            'Use grep or read_file to find valid paragraph IDs.',
          );
        }
    
        let start = 0;
        let end: number;
    
        if (params.anchor_text) {
          // Find anchor_text within the paragraph
          const paraText = session.doc.getParagraphTextById(pid) ?? '';
          const match = findUniqueSubstringMatch(paraText, params.anchor_text);
    
          if (match.status === 'not_found') {
            return err(
              'TEXT_NOT_FOUND',
              `anchor_text '${params.anchor_text}' not found in paragraph ${pid}`,
              'Verify anchor_text is present in the target paragraph.',
            );
          }
          if (match.status === 'multiple') {
            return err(
              'MULTIPLE_MATCHES',
              `Found ${match.matchCount} matches for anchor_text in paragraph ${pid}`,
              'Provide more specific anchor_text for a unique match.',
            );
          }
    
          start = match.start;
          end = match.end;
        } else {
          // Anchor to entire paragraph
          const paraText = session.doc.getParagraphTextById(pid) ?? '';
          end = paraText.length;
        }
    
        const result = await session.doc.addComment({
          paragraphId: pid,
          start,
          end,
          author: params.author,
          text: params.text,
          initials: params.initials,
        });
    
        manager.markEdited(session);
        return ok(mergeSessionResolutionMetadata({
          comment_id: result.commentId,
          anchor_paragraph_id: pid,
          anchor_text: params.anchor_text ?? null,
          mode: 'root',
          file_path: manager.normalizePath(session.originalPath),
        }, metadata));
      } catch (e: unknown) {
        return err('COMMENT_ERROR', errorMessage(e));
      }
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/UseJunior/safe-docx'

If you have feedback or need assistance with the MCP directory API, please join our Discord server