Skip to main content
Glama

delete_footnote

Remove a footnote and its reference from a DOCX document to clean up content and maintain formatting.

Instructions

Delete a footnote and its reference from the document.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
file_pathYesPath to the DOCX file.
note_idYesFootnote ID to delete.

Implementation Reference

  • Core implementation of footnote deletion logic in docx-core.
    export async function deleteFootnote(
      documentXml: Document,
      zip: DocxZip,
      params: { noteId: number },
    ): Promise<void> {
      const { noteId } = params;
    
      const footnotesXml = await zip.readText('word/footnotes.xml');
      const footnotesDoc = parseXml(footnotesXml);
    
      const fnEl = findFootnoteById(footnotesDoc, noteId);
      if (!fnEl) throw new Error(`Footnote ID ${noteId} not found`);
      if (isReservedFootnote(fnEl)) throw new Error(`Cannot delete reserved footnote ID ${noteId}`);
    
      // Remove from footnotes.xml
      fnEl.parentNode?.removeChild(fnEl);
      zip.writeText('word/footnotes.xml', serializeXml(footnotesDoc));
    
      // Remove footnoteReference elements from document.xml
      const refs = documentXml.getElementsByTagNameNS(OOXML.W_NS, W.footnoteReference);
      const refsToRemove: Element[] = [];
    
      for (let i = 0; i < refs.length; i++) {
        const ref = refs.item(i) as Element;
        const idStr = getWAttr(ref, 'id');
        if (idStr && parseInt(idStr, 10) === noteId) {
          refsToRemove.push(ref);
        }
      }
    
      for (const ref of refsToRemove) {
        const run = ref.parentNode as Element | null;
        if (!run) continue;
    
        // Remove only the footnoteReference element, not the entire run
        run.removeChild(ref);
    
        // If the run is now empty (no visible content), remove it
        if (!hasVisibleContent(run)) {
          run.parentNode?.removeChild(run);
        }
      }
    }
  • MCP tool handler wrapper for deleting a footnote.
    export async function deleteFootnote(
      manager: SessionManager,
      params: {
        file_path?: string;
        note_id?: number;
      },
    ): Promise<ToolResponse> {
      const resolved = await resolveSessionForTool(manager, params, { toolName: 'delete_footnote' });
      if (!resolved.ok) return resolved.response;
      const { session, metadata } = resolved;
    
      if (params.note_id == null) {
        return err('MISSING_PARAMETER', 'note_id is required.', 'Provide the footnote ID to delete.');
      }
    
      try {
        await session.doc.deleteFootnote({ noteId: params.note_id });
    
        manager.markEdited(session);
        return ok(mergeSessionResolutionMetadata({
          note_id: params.note_id,
          file_path: manager.normalizePath(session.originalPath),
        }, metadata));
      } catch (e: unknown) {
        const msg = errorMessage(e);
        if (msg.includes('reserved')) {
          return err('RESERVED_TYPE', msg, 'Reserved footnotes (separator, continuationSeparator) cannot be deleted.');
        }
        if (msg.includes('Missing file in .docx: word/footnotes.xml')) {
          return err('NOTE_NOT_FOUND', `Footnote ID ${params.note_id} not found`, 'Use get_footnotes to list available footnotes.');
        }
        if (msg.includes('not found')) {
          return err('NOTE_NOT_FOUND', msg, 'Use get_footnotes to list available footnotes.');
        }
        return err('FOOTNOTE_ERROR', msg);
      }
    }

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