get_footnotes
Retrieve all footnotes from a DOCX file, including their IDs, display numbers, text, and anchored paragraph IDs.
Instructions
Get all footnotes from the document with IDs, display numbers, text, and anchored paragraph IDs. Read-only.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | Path to the DOCX file. |
Implementation Reference
- Main tool handler for 'get_footnotes' - resolves session, calls session.doc.getFootnotes(), maps results to {id, display_number, text, anchored_paragraph_id}, and returns with file_path metadata.
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)); } } - Core implementation - reads word/footnotes.xml, parses footnote elements, builds display number map from document reference order, finds anchored paragraph IDs, extracts text, sorts by display number.
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; } - Tool catalog registration with name 'get_footnotes', description, input schema (file_path required), and readOnlyHint annotation.
{ name: 'get_footnotes', description: 'Get all footnotes from the document with IDs, display numbers, text, and anchored paragraph IDs. Read-only.', input: z.object({ ...FILE_FIELD, }), annotations: { readOnlyHint: true, destructiveHint: false }, }, - packages/docx-mcp/src/server.ts:23-28 (registration)Import of getFootnotes handler in the MCP server module.
import { getFootnotes } from './tools/get_footnotes.js'; import { addFootnote } from './tools/add_footnote.js'; import { updateFootnote } from './tools/update_footnote.js'; import { deleteFootnote } from './tools/delete_footnote.js'; import { compareDocuments_tool } from './tools/compare_documents.js'; import { extractRevisions_tool } from './tools/extract_revisions.js'; - packages/docx-mcp/src/server.ts:133-134 (registration)Dispatch case in the CallToolRequest handler routing 'get_footnotes' to the getFootnotes function.
case 'get_footnotes': return await getFootnotes(sessions, args as Parameters<typeof getFootnotes>[1]); - Document class method getFootnotes() that delegates to the core getFootnotesImpl from footnotes.ts.
async getFootnotes(): Promise<Footnote[]> { return getFootnotesImpl(this.zip, this.documentXml); }