Appearance
OOXML Agent Context
This repository has project-scoped Codex MCP configuration in .codex/config.toml. Codex loads it only when the project is trusted. In a running Codex session, use /mcp to confirm the active servers.
Configured MCP Servers
ooxml
Endpoint: https://api.ooxml.dev/mcp
Purpose: ECMA-376 / Office Open XML reference lookup. This is a third-party MCP server, not an ISO, Ecma, or Microsoft service. Treat it as a fast retrieval and schema navigation layer, then verify behavior with generated fixtures and the OOXML validator.
Available tool families:
- Prose search over ECMA-376:
ooxml_search,ooxml_section,ooxml_parts. - Deterministic schema lookup:
ooxml_element,ooxml_type,ooxml_children,ooxml_attributes,ooxml_enum,ooxml_namespace. - OPC package metadata:
ooxml_package_part.
Use it when you need to answer questions such as:
- Which children are legal under a PresentationML or DrawingML element?
- Which attributes and enum values are valid?
- Which package content type or relationship type belongs to a
.pptxpart? - Which ECMA-376 section describes a serialization rule?
microsoft_learn
Endpoint: https://learn.microsoft.com/api/mcp
Purpose: official Microsoft documentation retrieval. Use this for Microsoft Open Specifications and implementation behavior, especially when PowerPoint accepts, repairs, extends, or rejects OOXML in ways that are not obvious from the schema.
Available tools:
microsoft_docs_search: search Microsoft Learn and official Microsoft docs.microsoft_docs_fetch: fetch a full Microsoft documentation page as markdown.microsoft_code_sample_search: search official Microsoft code samples.
Use it when you need to answer questions such as:
- What does
[MS-PPTX]say about a PowerPoint extension element? - What does
[MS-OI29500]say about Office implementation behavior? - How does the Open XML SDK validate or model a package part?
- Is a namespace, extension URI, or relationship type Microsoft-specific?
Known MCP Gap: Annex D Preset Shape Geometry Definitions
The ooxml MCP indexes the ECMA-376 main spec PDFs (Parts 1–4) and the transitional XSDs. It does not index the Annex D electronic addenda (OfficeOpenXML-DrawingMLGeometries.zip inside the Part 1 ZIP), which is where the per-shape adjust-value guide names and geometry formulas live. Searching the MCP for things like "round2SameRect adj1 adj2" returns nothing useful.
For preset-shape adj guide names, use the local reference file:
docs/preset-shape-adj-guides.tsv: complete shape → adj guide name mapping for all preset shapes that take adjust values. Sourced from ECMA-376 Annex D, cross-checked against LibreOfficeoox-drawingml-adj-namesand ONLYOFFICEOOXMLShapes/implementations.
For full geometry formulas (avLst defaults, gdLst, path construction), the best external fallbacks are:
- ONLYOFFICE/core
OOXMLShapes/: each shape has its own.cppfile with the full avLst and gdLst inline as XML strings. - LibreOffice/core
presetooxhandleadjustmentrelations.cxx: adj handle constraints.
Retrieval Workflow
- Start with local evidence. Search
src/,test/,tools/ooxml-validator/,README.md, anddocs/testing.mdbefore changing behavior. - Use
ooxmlfor normative structure: schema order, child elements, attributes, simple type enums, namespaces, and OPC package metadata. - Use
microsoft_learnfor PowerPoint-specific behavior, Microsoft extension namespaces, Open XML SDK behavior, and Office compatibility notes. - If the two sources disagree, document the difference in the code comment or test name only when it affects the implementation. Prefer PowerPoint and Open XML SDK behavior for this library's generated
.pptxcompatibility. - Validate with a minimal generated fixture. For serialization changes, add or update a focused case in
test/schema-cases.jsand runpnpm run test:schema. When the only valid oracle is genuine PowerPoint output and no such fixture exists yet, stop rather than guess: see Evidence and fixtures.
What Not To Do
- Do not commit full OOXML standards PDFs, large copied spec excerpts, or bulk extracted standard text.
- Do not rely on schema validity alone for user-visible compatibility. Some PowerPoint "needs repair" failures are implementation constraints caught by Open XML SDK validation or by opening the deck in PowerPoint.
- Do not introduce ad hoc XML ordering rules without either a local fixture, a PowerPoint-authored comparison, or a referenced standard/source note.
- Do not treat Microsoft extension namespaces as ECMA-defined without checking the Microsoft documentation.
Emitting XML: The el() Builder
src/gen/oxml/el.ts is the write-side element builder (mirror of src/read/oxml/dom.ts). Prefer it over template-string concatenation in new emitter code: it escapes text and attribute values centrally, so a forgotten encodeXmlEntities cannot produce invalid XML.
el(name, attrs, children, fmt)always emits a paired tag;voidEl(name, attrs, fmt)always self-closes. Self-closing is chosen by which function you call, never by the child's value:encodeXmlEntities(undefined)is'', so a value-based rule would silently rewrite<dc:title></dc:title>as<dc:title/>.raw(xml)interpolates already-serialized markup verbatim (child elements, or values that are deliberately not escaped).- Nullish attributes and children are dropped, so optional parts inline as
cond ? raw(...) : null. fmt(openPrefix/childPrefix/closePrefix) places whitespace explicitly. Most parts are flat and need nofmt; the pretty-printed ones are not always depth-regular, so indentation is described per element rather than derived.- Attribute values and text children take different escapers, and the difference matters. Attributes go through
encodeXmlAttrValue, which additionally emits	/ / for tab/CR/LF, because XML 1.0 §3.3.3 has a parser normalise those literal characters to a single space inside an attribute value before any consumer sees them. Text children go throughencodeXmlEntities, where the same characters are content and stay literal. Any emitter that writes an attribute with a template string rather than the builder (there are a few, e.g.cNvPrOpen) must callencodeXmlAttrValueitself.
Migrating an existing emitter onto it is a byte-preserving refactor: gate it with pnpm run byte-identity:baseline / :check (see AGENTS.md "Verification").
Local Validation Tools
- Install the validator once with
./tools/ooxml-validator/install.sh. - Run OOXML fixtures with
pnpm run test:schema. - Run the normal regression suite with
pnpm run test:unit. - Run the full default test command with
pnpm testwhen both regression and schema validation are relevant.
Useful local files:
tools/ooxml-validator/README.mdtest/schema-cases.jstest/schema-validation.test.jstest/validator.jssrc/gen/(OOXML generators:define/*normalize,slide|drawingml|chart|pres|opc|anim|table/*serialize)src/gen/oxml/el.ts(XML element builder used by the emitters)scripts/byte-identity.mjs(byte-identity gate for emitter refactors)scripts/raw-xml-ratchet.mjs(ratchet: hand-built XML may shrink, never grow)