Skip to main content
Glama

get_footnotes

Extract footnotes from DOCX files with IDs, numbers, text, and paragraph references for document analysis.

Instructions

Get all footnotes from the document with IDs, display numbers, text, and anchored paragraph IDs. Read-only.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
file_pathYesPath to the DOCX file.

Implementation Reference

  • The MCP tool handler for "get_footnotes" that resolves the document session and calls `session.doc.getFootnotes()`.
    export async function getFootnotes(
      manager: SessionManager,
      params: {
        file_path?: string;
      },
    ): Promise<ToolResponse> {
      const resolved = await resolveSessionForTool(manager, params, { toolName: 'get_footnotes' });
      if (!resolved.ok) return resolved.response;
      const { session, metadata } = resolved;
    
      try {
        const footnotes = await session.doc.getFootnotes();
        return ok(mergeSessionResolutionMetadata({
          footnotes: footnotes.map((f) => ({
            id: f.id,
            display_number: f.displayNumber,
            text: f.text,
            anchored_paragraph_id: f.anchoredParagraphId,
          })),
          file_path: manager.normalizePath(session.originalPath),
        }, metadata));
      } catch (e: unknown) {
        return err('FOOTNOTE_ERROR', errorMessage(e));
      }
    }
  • The core implementation logic that parses OOXML footnotes and returns the data structure used by the MCP tool.
    export async function getFootnotes(zip: DocxZip, documentXml: Document): Promise<Footnote[]> {
      const footnotesText = await zip.readTextOrNull('word/footnotes.xml');
      if (!footnotesText) return [];
    
      const footnotesDoc = parseXml(footnotesText);
      const fnEls = footnotesDoc.getElementsByTagNameNS(OOXML.W_NS, W.footnote);
      if (fnEls.length === 0) return [];
    
      const displayMap = buildDisplayNumberMap(documentXml, footnotesDoc);
    
      // Build map of footnoteReference id → anchored paragraph bookmark id
      const anchorMap = new Map<number, string | null>();
      const refs = documentXml.getElementsByTagNameNS(OOXML.W_NS, W.footnoteReference);
      for (let i = 0; i < refs.length; i++) {
        const ref = refs.item(i) as Element;
        const idStr = getWAttr(ref, 'id');
        if (!idStr) continue;
        const id = parseInt(idStr, 10);
        if (anchorMap.has(id)) continue;
    
        // Walk up to enclosing <w:p>
        let parent = ref.parentNode;
        while (parent && parent.nodeType === 1) {
          const pel = parent as Element;
          if (pel.localName === W.p && pel.namespaceURI === OOXML.W_NS) {
            anchorMap.set(id, getParagraphBookmarkId(pel));
            break;
          }
          parent = parent.parentNode;
        }
      }
    
      const footnotes: Footnote[] = [];
    
      for (let i = 0; i < fnEls.length; i++) {
        const el = fnEls.item(i) as Element;
        if (isReservedFootnote(el)) continue;
    
        const idStr = getWAttr(el, 'id');
        if (!idStr) continue;
        const id = parseInt(idStr, 10);
    
        const text = extractFootnoteText(el);
        const displayNumber = displayMap.get(id) ?? 0;
        const anchoredParagraphId = anchorMap.get(id) ?? null;
    
        footnotes.push({ id, displayNumber, text, anchoredParagraphId });
      }
    
      // Sort by display number (document order)
      footnotes.sort((a, b) => a.displayNumber - b.displayNumber);
    
      return footnotes;
    }

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