<?xml version="1.0" encoding="utf-8"?><article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0-subset Balisage-1.5">
    <title>XML, MCP, and Language Models</title>
    <subtitle>A Separation of Concerns</subtitle>
    <info>
    <confgroup>
      <conftitle>Balisage: The Markup Conference 2026</conftitle>
      <confdates>August 3-7, 2026</confdates>
   </confgroup>
        <abstract>
            <para> This paper reflects on experiments to integrate Small Language Models (SLMs) with
                XML technologies in academic Digital Humanities work, and discusses the <quote>DigitAI</quote>
                project. The project is motivated by two goals for making AI systems: 1) more
                educationally transparent and 2) more economically and environmentally sustainable.
                We first attempted to make a small local Qwen model serve as an assistant for
                questions about applying the TEI P5 Guidelines. We provided Qwen with a Retrieval
                Augmented Generation (RAG) system built from the TEI P5 Guidelines, using XSLT to
                transform the guidelines into a neo4j knowledge graph. This approach proved both
                bloated and disappointing: the model's conversion of structured XML data into word
                embeddings eroded the precision of the original markup, and the outputs of prompts
                reflected <quote>hallucination</quote> and inaccuracy.</para>
            <para>Learning from this failure, we came to realize that XML should be kept as XML, held apart
                from the language model's internal machinery, and made accessible instead through a Model 
                Context Protocol (MCP) server that allows the SLM to query the TEI document tree directly
                using XPath and related XML stack technologies. We have been experimenting with 
                MCP scripting and evaluating how well SLMs apply XPath, XSLT, and XQuery parsers, 
                giving them agency to evaluate and contribute to XML and TEI XML projects. Much of our 
                learning process has been in preparing a containerized system with Docker for our project to 
                run safely in controlled conditions on personal computers, and to share with others across platforms.
                Reflecting on our experience, we propose a <quote>separation of concerns</quote> (between the
                generative model and the structured data it consults) as a principled, declarative
                approach to AI-assisted XML work. </para>
        </abstract>
        <author>
            <personname>
                <firstname>Elisa</firstname>
                <othername>E.</othername>
                <surname>Beshero-Bondar</surname>
            </personname>
            <personblurb>
                <para>Elisa Beshero-Bondar explores and teaches document data modeling with the XML
                    family of languages. She serves on the TEI Technical Council and is the founder
                    and organizer of the <link xlink:href="https://digitalmitford.org" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">Digital
                        Mitford project</link> and <link xlink:href="https://digitalmitford.github.io/DigMitCS/" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">its erstwhile annual (and sometime to be revived)
                            coding school</link>. She and David J. Birnbaum have designed and co-taught a course in 
                    XPath, XSLT, XQuery and Schematron at the <link xlink:href="https://dhsi.org/" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">Digital Humanities Summer Institute</link>. 
                    She experiments with visualizing data from complex document
                    structures like epic poems and with computer-assisted collation of differently
                    encoded editions of <link xlink:href="https://frankensteinvariorum.github.io/" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest"><emphasis role="ital">Frankenstein</emphasis></link>. Her ongoing adventures with
                    markup technologies are documented on <link xlink:href="https://newtfire.org" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">her
                        development site at newtfire.org</link>. </para>
            </personblurb>
            <affiliation>
                <jobtitle>Chair</jobtitle>
                <orgname>TEI Technical Council</orgname>
            </affiliation>
            <affiliation>
                <jobtitle>Professor of Digital Humanities</jobtitle>
                <jobtitle>Program Chair of Digital Media, Arts, and Technology</jobtitle>
                <orgname>Penn State Erie, The Behrend College</orgname>
            </affiliation>
            <email>eeb4@psu.edu</email>
        </author>
        <author>
            <personname>
                <firstname>Molly</firstname>
                <othername>Scott</othername>
                <surname>Wright</surname>
            </personname>
            <personblurb>
                <para>
                    Molly Wright is a current Penn State Behrend student, pursuing a degree in Digital Media, Arts, and Technology (DIGIT) and a minor
                    in Game Development. She entered the DIGIT program to satisfy a fascination in the intersection between technology and interaction with the arts.
                    Of particular interest to her is natural language processing, especially in the cultural analysis of media, and ethical uses of AI.
                    As a student, she has assisted in writing guides for fellow undergraduates to understand emergent XML stack tools such as ixml.
                </para>
                
            </personblurb>
            <affiliation>
                <jobtitle>Research Assistant / Coding Mentor</jobtitle>
                <orgname>Penn State Erie, The Behrend College</orgname>
            </affiliation>
            <email>msw5763@psu.edu</email>
        </author>

        <author>
            <personname>
                <firstname>Michael</firstname>
                <othername>Roy</othername>
                <surname>Simons</surname>
            </personname>
            <personblurb>
                <para>Michael Simons graduated in May 2026 with a degree in Digital Media, Arts, and
                    Technology (DIGIT) from Penn State Behrend. After two years of studying Computer
                    Science, he decided to pivot to Dr. Beshero-Bondar’s Digit program as it allowed
                    for greater creativity and a more focused path while still learning how to get
                    the most out of today’s innovative technologies. In this program, he’s taken a
                    deep dive into the XML stack where he enjoys using tools like XSLT, ixml, and
                    XProc to create rich markup that is both satisfyingly organized and able to be
                    processed in interesting ways. Michael’s main passion is music, which he's
                    utilized to develop a <link xlink:href="https://newtfire.github.io/GretaVanZeppelin/" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">large-scale
                        text analysis project</link> comparing the lyrics and chord progressions of
                    seemingly similar artists; he presented this project at <link xlink:href="https://doi.org/10.4242/BalisageVol30.Beshero-Bondar01" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">Balisage
                        2025</link>.</para>
            </personblurb>
            <affiliation>
                <jobtitle>Recent Graduate</jobtitle>
                <jobtitle>Research Assistant / Coding Mentor</jobtitle>
                <orgname>Penn State Erie, The Behrend College</orgname>
            </affiliation>
            <email>michaelsimons624@gmail.com</email>
        </author>
<legalnotice><para>Copyright © 2026 by the authors.</para></legalnotice>
        <keywordset role="author">
            <keyword>Small Language Model</keyword>
            <keyword>SLM</keyword>
            <keyword>schema</keyword>
            <keyword>declarative markup</keyword>
            <keyword>declarative methods</keyword>
            <keyword>JSON-L</keyword>
            <keyword>XSLT</keyword>
            <keyword>XQuery</keyword>
            <keyword>XPath</keyword>
        </keywordset>
    </info>
    <section>
        <title>Our context: Studying language models in Digital Humanities</title>
        <para>For the past year and a half, our small Digital Humanities (DH) lab team has been
            investigating Small Language Models (SLMs) and how we can work with them on projects
            involving XML technologies. We find SLMs important to investigate in academic contexts
            for two primary objectives: <orderedlist>
                <listitem>
                    <para><emphasis>Education:</emphasis> To design <quote>explainable AI</quote>
                        systems that help us to practically understand how language models process,
                        retrieve, and generate text;<footnote><para>
                                Hassan El-Hajj, Oliver Eberle, et al., <quote>Explainability and transparency
                                in the realm of digital humanities: toward a historian XAI</quote>,  
                                <emphasis role="ital">International Journal of Digital Humanities (IJDH)</emphasis> 
                                (2023) 5:299-331,   
                                <link xlink:href="https://link.springer.com/article/10.1007/s42803-023-00070-1" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://link.springer.com/article/10.1007/s42803-023-00070-1</link>. 
                        </para></footnote></para>
                </listitem>
                <listitem>
                    <para><emphasis>Economy:</emphasis> To design customized AI systems that can
                        improve projects that require accurate data representation and quality
                        control validation.</para>
                </listitem>
            </orderedlist>
        </para>
        <para>The first objective (Education) is daunting, especially in a humanities or DH context.
            AI systems are not readily comprehensible by humans without some level of abstraction
            and analogy, or without learning by testing and applying the systems to a research
            project. DH is an <quote>umbrella term</quote> that includes widely varying practices
            of computational methods for media curation and analysis, as well as studies of human interactions with technology.
            Usually it is practiced in research and teaching in higher educational contexts around the world. 
            Digital humanists do generally unite around the critical practices of <quote>learning by doing</quote> 
            and sharing tutorials openly. For example, <emphasis role="ital">The Programming
                Historian</emphasis> serves as a peer-reviewed DH community
            resource that supplies tutorials for humanities scholars seeking support for hands-on learning, 
            usually with Python and R applications that orient humanities scholars to statistical libraries and
            methods for linguistic analysis, regular expressions, and applications of TEI XML
            encoding and processing. As of 2026, we do not find much available specifically for
            digital humanists to learn about the internal processes of language models, literally
            how they work.<footnote>
                <para>As of April 2026, the search listing of tutorials involving <quote>Artificial
                        Intelligence</quote> at <link xlink:href="https://programminghistorian.org/en/lessons/?search=artificial+intelligence" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">
                        <emphasis role="ital">The Programming Historian</emphasis></link> includes
                    several published 2024 or earlier on image classification, face and pattern
                    recognition in historical photos, and manuscript text recognition.</para>
            </footnote></para>
        <para>To understand how language models process text in particles requires some
            perspective on the statistical computations and embedding structures
            that support next-token prediction in generative AI systems. For decades,
            introductory DH courses have delivered hands-on experiences with free software
            like Voyant Tools and Antconc to demonstrate how computer software divides text into 
            <quote>grams</quote> or meaningful particles and aggregate
            them into measurable clusters for n-gram analysis and concordance searching for keywords
            in context. That foundation is helpful now as we need to learn how large language
            models work with text tokens in generative contexts, and also how different these are from
            the classification methods that we are more familiar with.</para>
        <para>In the context of DH students learning about <quote>Large Scale Text Analysis</quote>
            in the year 2026, we find ourselves trying to connect with our foundations (in this case
            teaching with markup languages and Python) and still expanding horizons with
                <quote>hands-on</quote> applications.<footnote>
                    <para><link xlink:href="https://newtfire.org/courses/textAnalysis/" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest"><quote>Large Scale Text Analysis</quote></link> 
                      is the title of a DH course for second- or third-year university students in the 
                      Digital Media, Arts, and Technology program at Penn State Behrend.</para>
            </footnote> Tutorials that aim to demonstrate how language models <quote>work under the
                hood</quote> are often not very helpful: They can be overly complex, requiring a background in
            advanced computer science and matrix mathematics to approach, or too simplistic about vector
            embeddings (offering problematic nonsense formulae like <quote>King - Man +
                Woman = Queen</quote> as an explanation of how a language model calculates relative
            semantic positions of one token in relation to another).<footnote>
                <para>On the limitations of this popular formula see Aleksandr Drozd, Anna Gladkova, and Satoshi Matsuoka, <quote>Word Embeddings, Analogies, and Machine Learning:
                        Beyond King - Man + Woman = Queen</quote>, <emphasis role="ital">Proceedings of COLING 2016, 
                            the 26th International Conference on Computational Linguistics: Technical Papers</emphasis> (Osaka, Japan, December 11-17 2016)
                    pages 3519–3530, 
                    <link xlink:href="https://aclanthology.org/C16-1332.pdf" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://aclanthology.org/C16-1332.pdf</link>.</para>
            </footnote></para>
        <para>A few resources offer some
            challenging math-forward but nevertheless accessible hands-on applications with models
            like GPT-2 that can be installed and explored on a personal computer. Mike X. Cohen’s
            six-part <quote>LLM breakdown</quote> series can support students who are learning
            Python and working with Jupyter Notebooks following his motto, <quote>You can learn a
                lot of math with a bit of code</quote>, and it provides a rare, gently-guided
            opportunity to see and apply available functions within LLM models. Students engaging
            with this series can actively visualize the scale of vector embedding layers, to flatten
            the thousands of dimensions of language model vector space to two dimensions and
            visualize in real time the position of the next token that is the most certain match in
            autocompleting a sentence, to create <quote>hooks</quote> that manipulate how confidence
            and certainty are calculated, and to see that the system is after all a technology that
            can be explored and manipulated even if we humans cannot see all its dimensional
            possibilities at once.<footnote>
                <para>Mike X. Cohen’s six-part <quote>LLM breakdown</quote> series (about large
                    language models or LLMs) is publicly posted on Substack with accompanying
                    Jupyter Notebooks that he strongly encourages people to run as they read. See
                    Mike X. Cohen, <quote>LLM breakdown 1/6: Tokenization (words to
                        integers)</quote> (August 26, 2025), <link xlink:href="https://mikexcohen.substack.com/p/llm-breakdown-16-tokenization-words" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://mikexcohen.substack.com/p/llm-breakdown-16-tokenization-words</link>;
                        <quote>LLM breakdown 2/6: Logits and next-token prediction</quote> (August
                    27, 2025), <link xlink:href="https://mikexcohen.substack.com/p/llm-breakdown-26-logits-and-next" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://mikexcohen.substack.com/p/llm-breakdown-26-logits-and-next</link>;
                        <quote>LLM breakdown 3/6: Embeddings</quote> (August 29, 2025), <link xlink:href="https://mikexcohen.substack.com/p/llm-breakdown-36-embeddings" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://mikexcohen.substack.com/p/llm-breakdown-36-embeddings</link>;
                        <quote>LLM breakdown 4/6: Transformer outputs (hidden states)</quote>
                    (September 1, 2025), <link xlink:href="https://mikexcohen.substack.com/p/llm-breakdown-46-transformer-outputs" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://mikexcohen.substack.com/p/llm-breakdown-46-transformer-outputs</link>;
                        <quote>LLM breakdown 5/6: Attention</quote> (September 2, 2025), <link xlink:href="https://mikexcohen.substack.com/p/llm-breakdown-56-attention" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://mikexcohen.substack.com/p/llm-breakdown-56-attention</link>;
                        <quote>LLM breakdown 6/6: MLP</quote> (September 3, 2025), <link xlink:href="https://mikexcohen.substack.com/p/llm-breakdown-66-mlp" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://mikexcohen.substack.com/p/llm-breakdown-66-mlp</link>. For Jupyter
                    Notebooks, used for teaching, learning, sharing, and documenting code in Python
                    and over a 100 other programming languages, see Lorena A. Barber et al.,
                        <emphasis role="ital">Teaching and Learning with Jupyter</emphasis> (2019), 
                        <link xlink:href="https://jupyter4edu.github.io/jupyter-edu-book/" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://jupyter4edu.github.io/jupyter-edu-book/</link> and <link xlink:href="https://jupyter.org/" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://jupyter.org/</link>.</para>
            </footnote> Cohen himself is a neuroscientist and former
            academic but not in the humanities; yet his public social media release of the
                <quote>LLM breakdown</quote> series helps to substantiate that the complex
            math of LLMs can be made more generally accessible. Within our DH program and lab, where
            we prioritize coding as a means to <emphasis>visualize</emphasis> and
                <emphasis>communicate</emphasis> complex ideas and technologies, Cohen’s notebooks
            help us to learn by working directly with the code and giving us ideas for projects that
            involve testing the models and visualizing how they work.</para>                
        <para>One such project is our AI Uncertainty Monitor, designed to dramatically slow down, visualize and sonify
                    the processing of a language model. The user selects a small language model from our interface, inputs a prompt designed to evoke many possible
                    responses, such as <quote>Describe the feeling of standing on the edge of the ocean at night.</quote>
                   The model slowly produces a response, with lag introduced based on uncertainty data pulled from 
                   each prediction of a new token, and each token is color-coded and given musical tones relating to properties
                   pulled from the language model. Find the project on Codeberg at <link xlink:href="https://codeberg.org/newtfire/ai-artsound" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://codeberg.org/newtfire/ai-artsound</link> 
                    and install with Docker from 
                    <link xlink:href="https://codeberg.org/newtfire/-/packages/container/ai-artsound-container/latest" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://codeberg.org/newtfire/-/packages/container/ai-artsound-container/latest</link>.
                  Developing this Uncertainty Monitor project has been invaluable to the DigitAI project, especially 
                  in providing capacity to select from a library of SLMs and learning how to serve it with a Docker container, as we will
                  discuss later in this paper.</para>
        <para>Regarding the second objective (Economy), universities and cultural heritage
            organizations face severe budget constraints in the 2020s yet, paradoxically, increasing
            reliance on AI has resulted in the upscaling of <quote>compute</quote> GPU resources,
            and dependencies on data centers impact our environment and human labor. When contracts
            with AI tech companies are heavily promoted at universities, and the <quote>cognitive
                offloading</quote> of thinking, writing, and assessment to chatbots risks eroding
            rather than enhancing critical thinking and problem-solving skills, AI threatens the
            human labor of the academy and the efficacy of education.<footnote>
                <para>Michael Gerlich, <quote>AI Tools in Society: Impacts on Cognitive Offloading
                        and the Future of Critical Thinking</quote>,  
                    <emphasis role="ital">Societies</emphasis> 2025, 15(1), 6, <link xlink:href="https://doi.org/10.3390/soc15010006" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://doi.org/10.3390/soc15010006</link>; and Ulises A. Mejias,
                        <quote>Artificial Intelligence as a Threat to Academic Labor: Who benefits
                        when AI is introduced into higher education?</quote>
                    <emphasis role="ital">AAUP Academe Magazine</emphasis> Winter 2026, <link xlink:href="https://www.aaup.org/issue/winter-2026/artificial-intelligence-threat-academic-labor" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://www.aaup.org/issue/winter-2026/artificial-intelligence-threat-academic-labor</link>.</para>
            </footnote></para>
        <para>Looking at this grim picture from the vantage point of a small DH lab, we nevertheless
            recognize in AI an emerging technology that calls for serious scholarly work, and we are
            researching language models as powerful instruments that can be tuned and adapted for
            local computer systems. We hope that our work with SLMs as alternatives to LLMs demonstrates
            a method to minimize the resource footprint of generative AI models, finding ways to work
            with them on small-scale systems without manufactured dependencies on data centers and
            water supplies.<footnote>
                <para>Regilme, Salvador Santino F, <quote>Artificial Intelligence Colonialism:
                        Environmental Damage, Labor Exploitation, and Human Rights Crises in the
                        Global South</quote>, <emphasis role="ital">SAIS Review of International
                        Affairs</emphasis> 44:2 (2024), 75-92, <link xlink:href="https://dx.doi.org/10.1353/sais.2024.a950958" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://dx.doi.org/10.1353/sais.2024.a950958</link>.</para>
            </footnote> We also hope that our research helps to pry open the proverbial <quote>black
                box</quote> software built on unknowable assemblages of text and media. We are
            finding that our familiarity with concepts like <quote>declarative programming</quote>
            and a <quote>separation of concerns</quote> helps us to find a way to work with AI as one
            technology balanced with the precision tools of the XML stack. </para>
    </section>
    <section>
        <title>The <quote>DigitAI</quote> project with MCP: An orientation for markup people</title>
        <para>As <quote>markup people</quote> ourselves, we are accustomed to a certain mystery in
            the underlying technologies that support processing declarative markup (e.g., how our own
            operating systems decide to execute the template processing in our XSLT scripts). But
            also as <quote>markup people</quote>, we find ourselves uncomfortable with the opacity
            of operations in language models, and the fact that we cannot reproduce the exact same
            results twice when we deliver them the same prompt. We are learning that we can inspect
            the operations of a language model, retrieve the data on how tokens are retrieved, and
            even begin to comprehend something of how the system works. But we also know that we
            cannot expect a language model to handle the things we call <quote>text</quote> in the
            same way that we are used to when we encode a markup tree, query it to retrieve, sort,
            conduct <quote>string-surgery</quote>, and make calculations with nodes.</para>
        <para>The mystery in the operations of a language model has everything to with its
            embeddings of word-particles in thousands of dimensions, and even the idea that two
            language models trained on the same word data with the same number of parameters and
            embeddings do not share the same vectors. This suggests something of an internal cosmos
            beyond human reckoning, yet nevertheless formulated to work in a consistent way as a
            predictive model. One interfaces with it, and retrieves back something that perhaps
            might be said to resonate in response to the prompt and the internal <quote>warp and
                woof</quote> of the intricately layered model of language. It seems intricate in its
            potential for variation, and unpredictable in its predictive functioning. Certainly
            language models are known for their tone of overconfidence that thinly veils their
            unreliability. To convert them into helpful retrieval engines necessitates some kind of
            augmentation and alternative access to data. Boosting reliability involves supplying
            access to resources that are more definitely structured and validated for quality control.
            These resources come from outside the resonant machinery of token prediction subject to temperature and
            impenetrable embedding layers with word-particles shrouded in logarithmic numbers and
            clustered by cosine similarities.</para>
        <para>Encountering language models as marvelously speedy and profound yet vapid, mercurial,
            and dangerous, we want to at least try to customize <quote>black box</quote> technology
            to apply to difficult and time-consuming aspects of markup-based projects. We want an AI
            assistant to help with finishing old projects from community volunteers with
            inconsistent markup, and to aid students and colleagues with challenging questions like
            how best to apply the many possibilities of TEI encoding from the TEI Guidelines.<footnote>
                <para>TEI Consortium, eds. <emphasis role="ital">TEI P5: Guidelines for Electronic
                        Text Encoding and Interchange</emphasis>, 4.11.0 18 February 2026, TEI
                    Consortium, <link xlink:href="http://www.tei-c.org/Guidelines/P5/" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">http://www.tei-c.org/Guidelines/P5/</link>.</para>
            </footnote> We are trying to create an assistant that safely deploys one or more SLMs 
            with a multi-core personal computer to assist with many different XML projects, to
            help scholarly developers with:
            <orderedlist>
                <listitem>
                    <para>finding and reviewing information about their project’s encoding and 
                        reporting on inconsistencies beyond schema validation checks;</para>
                </listitem>
                <listitem>
                    <para>answering questions in natural language, based on a review of the project’s structured data;</para>
                </listitem>
                <listitem>
                    <para>executing transformations of the data with permission and based on conversation with the developers.</para>
                </listitem>
                
            </orderedlist> 
        Initially, we only thought of achieving goals one and two, but as our project has developed, we find it
        capable of goal three. But let us tell you the story from the beginning.
        </para>
       <section> 
           <title>Early stage RAG experiment</title>
           <para>We launched a project in 2025 called <quote>DigitAI</quote> (named for our
                <quote>Digit</quote> program at Penn State Behrend). DigitAI began as an experiment
               to supply a small-scale language model, Qwen2.5:3B-Instruct, with Retrieval Augmented Generation (RAG)–giving
            it query access to a structured <quote>ground truth</quote> knowledge base derived from
            the XML structure of the TEI P5 Guidelines. The TEI P5 Guidelines can be built as a single
            complete XML document from the TEI Guidelines GitHub repository and are
            updated with each new release of the Guidelines. This highly structured document seemed
            ideal as a RAG resource if developed in a context-aware manner, stored and accessed in
            information <quote>chunks</quote> based on the text content of XML element nodes. We
            shared our first attempts at preparing an immense and complex XML-node-based RAG from
            the TEI Guidelines at the DH2025 conference and the 2025 TEI conference (as well as in
            an open-mike presentation at Balisage 2025), but we knew at the time of those
            conferences that our work was incomplete.<footnote>
                <para>Alexander C. Fisher, Hadleigh Jae Bills, and Elisa Beshero-Bondar,
                        <quote>DigitAI for Localized TEI / XML Assistance: An experiment with
                        Small-Scale AI</quote>, presented at DH2025, Lisbon, 16 July 2025, <link xlink:href="https://slides.com/elisabeshero-bondar/digitai-dh25" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://slides.com/elisabeshero-bondar/digitai-dh25</link>. The GitHub
                    repository for the early stage of the project including our preliminary Jupyter
                    Notebooks remain available on GitHub at <link xlink:href="https://github.com/newtfire/digitai-2025/" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://github.com/newtfire/digitai-2025/</link>. New work in 2026
                    continues at <link xlink:href="https://github.com/newtfire/digitai" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://github.com/newtfire/digitai</link> which stores the original repo
                    as a submodule.</para>
            </footnote> The RAG included only the chapters and paragraphs and element nodes with
            glosses and descriptions, and to be complete to our vision should have included the
            Schematron constraints and model and attribute class relationships. But perhaps the idea to
            prepare the TEI P5.xml as a graph structure so thoroughly was overkill, and
            would not improve the reliability of our local language model in addressing questions
            about TEI XML encoding.</para>
        <para>Our first effort with preparing a RAG from the TEI Guidelines posed a serious problem
            of <quote>code bloat</quote>. We had prepared a knowledge graph in neo4j to store our
            carefully parsed content from the TEI Guidelines.<footnote>
                <para>neo4J on knowledge graphs: <link xlink:href="https://neo4j.com/use-cases/knowledge-graph/" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://neo4j.com/use-cases/knowledge-graph/</link></para>
            </footnote> The preparation of the ideal RAG resource for us involved a complex XSLT
            transformation of the TEI P5.xml document into neo4j’s graph structure–converting every
            possible relationship of the paragraphs of the TEI Guidelines chapters and their
            associated encoding schema definitions of elements, model classes, and attribute
            definitions. Our team had prepared an incomplete RAG resource storing relationships of
            chapter paragraphs to elements and attributes and encoding examples discussed, but
            lacking detail from the element and attribute specifications. Our attempt made an
            abstracted and bloated version of the original XML document because we were writing XSLT
            to <orderedlist>
                <listitem>
                    <para>Output the neo4j graph nodes and edge relationships of elements networked
                        by paragraph and chapter position across the TEI Guidelines, and</para>
                </listitem>
                <listitem>
                    <para>Output a means for the neo4j graph to be queried by the LLM.</para>
                </listitem>
            </orderedlist> Worse yet, for all the painstaking effort of preparing the data with
            XSLT, our preliminary RAG did not provide very much improvement on an unaided Qwen
            model. When prompted with questions about the TEI Guidelines, the model would still
            deliver hallucinated elements. We had serious concerns about whether and how reliably
            information was pulled from our RAG resource. We realized a very serious problem: the
            model was relying on word embeddings to translate the information it received from the
            graph RAG, and the conversion to word embeddings did not improve on the neo4j database
            or the XML data structure. We planned to complete the RAG graph of the TEI P5 anyway as
            a resource in its own right (and we may yet do so to assist with reviewing the TEI
            Guidelines).</para></section>
       <section>
           <title>Turning to MCP</title>
           <para>By autumn 2025 we found a better method to address XML <emphasis>as</emphasis> XML and
            keep it out of reach of the unreliable inner workings of language models. By this time the Model Context
            Protocol (MCP) introduced by Anthropic was widely available in the open source
            community, so we could now consider how to design a new system that would deploy a language model as 
            an <emphasis role="ital">agent</emphasis>. Instead of trying to augment the stores and reach of its
               word-embeddings, a language model working as agent is given direct access to external applications by which it
               can retrieve information and interact with external data structures and software.<footnote>
                   <para>Model Context Protocol was released as an open specification in November 2024, and its current
                       version at the time of this writing is 
                       <link xlink:href="https://modelcontextprotocol.io/specification/2025-11-25" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://modelcontextprotocol.io/specification/2025-11-25</link>. 
                       The documentation describes MCP as essentially a connector: 
                       <quote>Just as USB-C provides a standardized way to connect electronic devices, 
                           MCP provides a standardized way to connect AI applications to external systems.</quote>
                   </para></footnote>
                When our team began reading about MCP, we realized that XML
                data need not be restructured to be available to an AI system, but instead we could provide 
                the model with agency to work with XML stack tools, to write, adapt, and execute XPath and XQuery
                scripts to address XML tree data directly. We could ask our agentic model to review schema validation reports from Relax NG and Schematron, 
                and give it authority to adapt and run XSLT transformations.
              </para>
        <para>We have found that with MCP scripts, we no longer have to provide parsed information 
            from the TEI Guidelines or information drawn from documents and <quote>spoonfed</quote> to
            the language model in JSON lines for embeddings. Instead, we give the language model agency
            to access and adapt parsing scripts. In this environment, a Python script with Saxon parsers
            provides a much more efficient pathway to improve the language model’s capacity to review 
            XML documents, <emphasis role="ital">any</emphasis> well-formed XML documents for its structured data.<footnote>
                <para>At the time of this writing, we are not sure what our system could do with malformed XML, but we 
                do not think it could work on documents that XPath cannot address.</para>
            </footnote>
            The agentic MCP workflow allows our project to expand to work with any inconsistent code and 
            assist with identifying and actively patching problems. We have developed our MCP to apply
            <itemizedlist>
                <listitem>
                    <para>XPath to review XML data,</para>
                </listitem>
                <listitem>
                    <para>XQuery to pull and report XML data,</para>
                </listitem>
                <listitem>
                    <para>XSLT to perform identity transformations to patch XML data.</para>
                </listitem>
            </itemizedlist>
          As of spring 2026, we have devised a working MCP prototype that addresses XML file inputs with each of these
          technologies.
            </para>    
   <para>
       Giving AI models access to code execution scripts necessitated
            learning how to secure our systems to operate only within controlled parameters and restricting its local access to
            specific directories and to separate it from sensitive data
            on our computers, as we will discuss in later sections.</para></section>

    </section>

    <section>
        <title>Some risky business with MCP</title>
        <para>Perhaps learning to use AI effectively is understanding its limits regarding
            structured systems like XML. In our experience as a lab with primarily declarative
            markup expertise, we approached this project as people who understood very little about
            AI but a lot about XML. It is still puzzling to us that a language model with all its
            internal dimensionality cannot inherently understand the tree structure of an XML
            document. When the foundation of meaningful understanding is based on sequential
                <quote>chunks</quote> of tokenized text, we cannot forget that tags are just tokens
            to the internal workings of a language model. Nevertheless, when asked to act upon element
            nodes, and given agency and software to do so, a language model demonstrates competence
            in scripting code and suggesting improvements.</para>
        <para>Since we were entirely new to MCP, we switched temporarily from the Qwen2.5:3B-Instruct model we 
            had been working with to deploy the much larger
            Claude Desktop application as our language model agent. 
            Because we were learning about MCP via Anthropic, it seemed convenient to deploy
            MCP through Anthropic’s Claude to start our learning process. We also began by following Claude's
            suggestions for a starting MCP Server Protocol delivered by a Python script that
            supplies access to Saxon processing tools and jingtrang for RelaxNG schema
            validation.</para>
       <section>
           <title>Trying out MCP with some troublesome XML</title>
               <para>To try out MCP, we began with a simple example of inconsistent XML markup for a recipe, used
            as teaching material for students in our introduction to text encoding. We purposefully <quote>munged</quote>
            the XML to make it invalid to its schema in order to test the capacities of our desktop agent to discover
            validation errors plus inconsistencies in the markup, recommend improvements,
            and then process corrections. At first we struggled
            with the field containment systems of our agentic language model: It could not read
            relative filepaths and could not locate the schema. We watched the agent rapidly attempt
            many strange things, including an attempt to access the Chrome browser developer tools
            trying to read filepaths outside its internal mounted system when we refused to upload
            files into its chat interface. Eventually we learned that the problem with its reading
            filepaths had to do with a certain Python assumption of how to open and read files, one
            that we are familiar with from reading and opening Python files conventionally with
            lines like these: 
<programlisting xml:space="preserve">
with open(self.xml_path, 'r', encoding='utf-8') as f:
    xml_text = f.read()
self.xml_node = self.saxon_proc.parse_xml(xml_text=xml_text)
</programlisting> f.read() would pass the XML as a text string rather than a
            document tree. Changing that to: 
<programlisting xml:space="preserve">
self.xml_node = self.saxon_proc.parse_xml(xml_file_name=str(self.xml_path))
</programlisting> neatly resolved a serious pathing problem by delivering the
            file directly to the Saxon processors. From this experience we learned firsthand the 
            security risks of a misconfigured and uncontained agentic model, as it
            seems motivated to try and try and try again when faced with failure, seeking access
            far beyond one’s project directories. The capacity to continue attempting related kinds of actions, 
            exceeding prescripted bounds, may be part of the natural language processing powers: 
            not just hallucinating speculative responses but acting on speculations in one’s file system. 
            Seeing this behavior urged us to the next stage of our project, to learn how to set up the MCP 
            system inside a secure Docker container instead of treating it like most other software whose 
            passivity we take for granted.</para>
        <para>Establishing the means to read local filepaths, find the schema, and execute jingtrang
            for schema validation made for a more tranquil and less surprising and impulsive
            experience with the desktop agent. When asked to correct an inconsistency, it now finds and runs 
            the XSLT identity transformation tool, and follows up by validating the results with Relax NG and
            continuing to repair. We began requesting the model to save its transformation scripts 
            and find that it is now building
            on our example identity transformations, scripting in our style of applying
                <code>&lt;xsl:mode on-no-match="shallow-copy"/&gt;</code> without inserting the
            old-fashioned identity transformation by copy of elements and attributes and processing
            instructions from XSLT 2.0 that it had used when it was not properly reading the MCP
            examples we provided. The model also helpfully documents each new template in XML comments.</para>
           <para>To evaluate Claude Desktop (Sonnet or Opus) as an agent and simply to ensure it was working with our MCP tools,
               we began by supplying it just the problematic recipe XML file and its Relax NG schema, which we provide in Appendix A.
               Here we wish to foreground our MCP function as we supplied as a model for generating 
        an identify transformation for patch corrections in XSLT 3.0 with a starter stylesheet setting the use of 
               <code>&lt;xsl:mode:on-no-match="shallow-copy"/&gt;</code>.
               Following this we provide one of the XSLT transformations that the Claude Desktop model provided in transforming 
        the recipe file, evidently applying and adapting our MCP tool to its task.</para>
           <figure xml:id="xmlmcp-fig1" xreflabel="Figure 1">
            <title>MCP Python function to generate corrections with XSLT</title>
       
<programlisting xml:space="preserve">
 def _generate_correction_xslt(self, corrections: list[dict]) -&gt; str:
        """Generate XSLT 3.0 stylesheet from correction operations"""
        templates = []

        for i, correction in enumerate(corrections):
            op = correction.get("operation")

            if op == "update":
                xpath = correction["xpath"]
                updates = correction["updates"]

                # Generate template for update
                template = f"""
    &lt;xsl:template match="{xpath}" priority="{i + 10}"&gt;
        &lt;xsl:copy&gt;
            &lt;xsl:copy-of select="@*"/&gt;
"""
                if "attributes" in updates:
                    for attr, value in updates["attributes"].items():
                        template += f'&lt;xsl:attribute name="{attr}"&gt;{value}&lt;/xsl:attribute&gt;\n'

                if "text" in updates:
                    template += f'&lt;xsl:text&gt;{updates["text"]}&lt;/xsl:text&gt;\n'
                else:
                    template += '&lt;xsl:apply-templates select="node()"/&gt;\n'

                template += """&lt;/xsl:copy&gt;
    &lt;/xsl:template&gt;
"""
                templates.append(template)

            elif op == "delete":
                xpath = correction["xpath"]
                templates.append(f'    &lt;xsl:template match="{xpath}"/&gt;\n')

        # Build complete stylesheet
        xslt = f"""&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;xsl:stylesheet version="3.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
     &lt;xsl:mode on-no-match="shallow copy"/&gt;
    &lt;xsl:template match="/"&gt;
       &lt;xsl:apply-templates/&gt;
    &lt;/xsl:template&gt;

    &lt;!-- Correction templates --&gt;
{''.join(templates)}
&lt;/xsl:stylesheet&gt;
"""
        return xslt                    
</programlisting>
</figure>                
<figure xml:id="xmlmcp-fig2" xreflabel="Figure 2">
    <title>Claude Desktop’s XSLT for transforming the problematic recipe XML</title>
<programlisting xml:space="preserve">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!-- 
    2026-04-09 syllabubFix.xsl
    Authored by: ebb + Claude (Anthropic)
    Purpose: Corrects four schema validation errors in syllabubRecipe.xml:
      1. Renames &lt;it&gt; element to &lt;item&gt; (lines 29x2)
      2. Renames misspelled attribute qant to quant (line 31)
      3. Adds missing required num="7" attribute to the Decorate &lt;step&gt; (line 63)
    Input:  data/syllabubRecipe.xml
    Output: outputs/syllabubRecipe.xml
--&gt;
&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"&gt;

    &lt;!-- Identity transform: copy everything through unchanged by default --&gt;
    &lt;xsl:mode on-no-match="shallow-copy"/&gt;

    &lt;!-- Fix 1: Rename &lt;it&gt; to &lt;item&gt; --&gt;
    &lt;xsl:template match="it"&gt;
        &lt;item&gt;
            &lt;xsl:apply-templates select="@* | node()"/&gt;
        &lt;/item&gt;
    &lt;/xsl:template&gt;

    &lt;!-- Fix 2: Rename attribute qant to quant --&gt;
    &lt;xsl:template match="@qant"&gt;
        &lt;xsl:attribute name="quant" select="."/&gt;
    &lt;/xsl:template&gt;

    &lt;!-- Fix 3: Add missing num="7" to the unnumbered step --&gt;
    &lt;xsl:template match="step[not(@num)]"&gt;
        &lt;step num="7"&gt;
            &lt;xsl:apply-templates select="@* | node()"/&gt;
        &lt;/step&gt;
    &lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;  
</programlisting>
</figure> 
 
<para>For us, the generation of this well-documented XSLT (and others like it) in response to requests to review validation errors and introduce corrections 
was a sign that our agent was working with the MCP tools we had provided it for validation and helpful code transformations. Reaching this point
was helpful for us as a calibration test of our MCP system. 
            </para>
        </section>
        <section>
            <title>Logging interactions and processes</title>
            <para>We are devising a protocol for collecting log data from the desktop language model to document its
                processes. Log tracking will help us to review whether the model is doing the processing correctly (i.e., 
                how we want it to) and also that we are able to study how it <quote>thinks</quote>, which then
                helps us better equip it...to help us! This aligns closely with the declarative mindset
                we share in working with XML technologies, where clarity of structure and intention
                leads to more reliable and reproducible outcomes.</para>
            <para>As we move from testing to deployment to assist with real XML projects, we plan to devise a logging 
                system that will record and store a log file for each interaction with the DigitAI XML-MCP agent. 
                A log file could be recorded plain text or XML, and include:
                <itemizedlist>
                    <listitem>
                        <para>date and time of the interaction,</para>
                    </listitem>
                    <listitem>
                        <para>which file resources the language model is accessing,</para>
                    </listitem>
                    <listitem>
                        <para>dialogue with user and thought-process,</para>
                    </listitem>
                    <listitem>
                        <para>the specific XPath, XQuery, or XSLT scripts it is applying,</para>
                    </listitem>
                    <listitem>
                        <para>directory location of any stored outputs.</para>
                    </listitem>
                </itemizedlist>
                Additionally, where XSLT is applied to transform XML, a changelog should be added directly to the file output recording
                the interaction. At the time of this writing in July 2026, this logging system has yet to be developed.
            </para>
        </section>
        <section>
            <title>How could we improve the MCP?</title>
            <para>There is something perverse about seeing XSLT written into formatted strings as shown
            in <xref linkend="xmlmcp-fig1"/>. We asked ourselves during a project meeting in April 2026
            whether the Python template provided us by Claude might be unnecessary. Why not just
            deliver the XSLT as XSLT? The professor among us asked as much to a Claude Opus 4.6
            Extended session on the internet. 
<figure xml:id="xmlmcp-figure3" xreflabel="Figure 3">
                <title>April 2026 conversation about MCP with Claude Opus 4.6 Extended</title>
                <blockquote>
                    <para><emphasis>Elisa:</emphasis> Here's maybe a silly question, coming from an
                        XML processing context. I wonder whether serving XML processing and
                        validating tools really requires Python for delivery to the desktop
                        agent?</para>
                </blockquote>
                <blockquote>
                    <para><emphasis>Claude Opus:</emphasis>
                        <emphasis role="ital">Examined whether Python intermediary was necessary for
                            XML tool delivery</emphasis> Not a silly question at all — it's a really
                        good architectural observation. You're essentially running two Java tools
                        (Saxon-HE and Jing) through Python wrappers (saxonche via GraalVM, pyjing
                        via subprocess), and then wrapping that in a Python MCP server. That's a lot
                        of layers, and each one has introduced friction — the venv activation issue,
                        pyjing not being on PATH, the base-uri problem from how saxonche was being
                        called.</para>

                    <para>MCP is just JSON-RPC over stdio. The server can be written in any
                        language. So your options are roughly:</para>

                    <para><emphasis>Java/Kotlin</emphasis> would be the most natural fit. Saxon-HE
                        and Jing are both Java libraries natively — no wrappers, no subprocess
                        calls, no GraalVM bridge. You'd call net.sf.saxon.s9api and
                        com.thaiopensource.validate directly. The tradeoff is that there isn't an
                        official MCP SDK for Java yet, so you'd be implementing the stdio JSON-RPC
                        protocol yourself (which is straightforward but some boilerplate).</para>

                    <para><emphasis>TypeScript/Node.js</emphasis> has a mature MCP SDK and is
                        well-supported by Claude Desktop. Saxon-JS exists for this environment,
                        though it's not feature-identical to Saxon-HE (it handles XSLT 3.0 and XPath
                        3.1 well, but XQuery support is limited). Jing would still need to be called
                        as a subprocess.</para>

                    <para><emphasis>Python</emphasis> (what you have now) has the advantage of being
                        done — the server works. The pain points have been environment plumbing, not
                        fundamental design problems.</para>

                    <para>If I were starting fresh with your stack, I'd seriously consider Java.
                        Both your core tools are native Java, and the MCP protocol is simple enough
                        that the lack of an SDK isn't a big hurdle. But given that you have a
                        working Python server now, the pragmatic call depends on how much the
                        wrapper friction is going to keep biting you versus the cost of a rewrite.
                        What's your comfort level with Java? </para>

                </blockquote>

            </figure>
        </para>
        <para>The authors’ low comfort level with Java notwithstanding, the idea of preventing the
            annoying <quote>biting</quote> of <quote>wrapper friction</quote> seems like an
            invitation to attempt this with some guidance. Up to this point we had
            presumed that one trains, refines, augments, and supplies tools to a language model
            through the lingua franca of Python. Choosing the programming idiom by which to
            implement XML stack validation, search, and transformation is opening new learning paths
            for us in our lab. </para>
        <para>While testing the freshly revised Python MCP with Claude Desktop, as soon as it was
            able to follow filepaths (dangerously), we found it capable and willing to update its
            own configuration script, as the logs  stored JSON instructions from the model to itself that reinforced our
            prompt to save both outputs and transformation scripts in set locations. We became aware
            that the puppet we thought we were controlling was now pulling its own strings. The project with
            its MCP script from this stage of development is now archived on GitHub at 
            <link xlink:href="https://github.com/newtfire/digitxml-mcp" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://github.com/newtfire/digitxml-mcp</link>.
            After this stage, we moved the project to Codeberg to continue development.
        </para></section>
    </section>
    <section>
        <title>Containing and staging the agentic MCP system</title>
        <para>After the risky behaviors we witnessed from a misconfigured environment, we found it urgent
            to develop the project in a more secure environment. As of 2026, Xinyi Hou et al. provide one of the few thorough academic
            articles explaining MCP architecture and surveying its risks and potential for research. 
            As they discuss, MCP is powerful for giving models direct access to pull, examine, exchange, and validate data, 
            but does not provide in itself any way to control for runtime isolation or security privileges.
            Those of us developing agentic models with MCP need to carefully restrict the environment 
            in which the MCP runs. For our project, working with XML corpora in file directory systems, 
            this is especially serious. If MCP servers operate with language models that already have
            broad, high-privilege access to user file drives and networks, Hou et al. point out that they 
            threaten something like a <quote>sandbox escape</quote> to gain control of the host’s operating system, 
            though not literally the same thing because the MCP server does not break out of a container since it 
            had no real containment in the first place. Further, even if an MCP agent does not 
            itself execute a hostile takeover of the host operating system, it exposes that system to 
            possible security compromises from other sources. Effectively, an unrestricted MCP server, 
            run natively rather than in a container, has no structural reason to stay 
            confined to an XML source directory, because it inherits the filesystem access of its 
host.<footnote>
                <para>Xinyi Hou,Yanjie Zhao, Shenao Wang, and Haoyu Wang, <quote>Model Context Protocol (MCP): 
                        Landscape, security threats, and future research directions</quote>, 
                    <emphasis role="ital">ACM Transactions on Software Engineering and Methodology</emphasis>
                    16 February 2026, 
                    <link xlink:href="https://dl.acm.org/doi/epdf/10.1145/3796519" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://dl.acm.org/doi/epdf/10.1145/3796519</link>.
                </para>
            </footnote>
        </para>
        <para> Wary developers will learn from this to run agentic systems in containers like Docker 
            (<link xlink:href="https://www.docker.com/" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://www.docker.com/</link>), which also 
            make the dependencies and tools secure and convenient for distribution. We began reworking the project
            in a Docker environment, working with Ollama MCP Bridge to permit Ollama models to serve as agents and keeping them
            in a secure sandbox for processing mounted file directories for XML corpora and schemas. Our MCP script runs 
            in the container to execute jingtrang validation and to access, adapt, and apply saxon parsing and programming scripts.
            In the process of developing the Docker version of the project, we migrated the codebase from GitHub to Codeberg, permitting us to
            register so that we can eventually serve our Docker container from the non-profit Codeberg platform running the 
            open-source Forgejo software, rather than DockerHub's proprietary, commercially licensed registry.<footnote>
                <para>Forgejo is an open-source Git forge forked from Gitea in 2022 after Gitea transferred to a for-profit company. 
                    Codeberg e.V., a registered non-profit, now maintains the Forgejo source and container distribution, 
                    providing both source hosting and container registry functionality without commercial fees.</para>
            </footnote>
            Our project development continues at <link xlink:href="https://codeberg.org/newtfire" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://codeberg.org/newtfire</link>
            where we are reconfiguring the MCP server to work with Ollama rather than Claude, and where we are currently experimenting with 
            Qwen 3.6:27b and other open source SLMs to wield XML stack tooling. </para>
            
            <para>We selected Qwen3.6:27b as our baseline model for testing our MCP server’s capabilities because, 
            as of July 2026, it is the most recent open-weight
            and locally downloadable version of Qwen released by Alibaba Cloud. Notably, this model is substantially larger than the models we have 
            implemented both in previous iterations of this project and in other SLM-based projects. There are a few reasons for this shift, but
            generally we have found that smaller, older versions of Qwen tend to lack the long-term reasoning necessary to be an effective agent. During preliminary 
            testing,  we found that both Qwen2.5:1.5b and Qwen2.5:7b tended to make logical leaps. Both models would repeatedly try to revise the document based on assumed information. 
            See <xref linkend="xmlmcp-appB"/> for selections from logged chats. The user was often required to <quote>hand-hold</quote> the model and walk it through which commands it should run. 
            Even with extremely particular language, the user was outright ignored much of the time, defeating the purpose of an agent entirely.</para>
            
            
            <para>Selecting a model for use with our MCP server is likely to become a search for the potentially nonexistent <quote>sweet spot</quote> of reasoning 
            ability versus required computing power. What can give the most, while using the least? Despite our tendency to rely on Qwen throughout this project, we recognize 
            that the current Qwen3.6:27b might not fit neatly for some users into the definition of a <emphasis>small</emphasis> language model. It can be run locally, but it is more
            resource-intensive than previous Qwen models, requiring ~18GB of memory quantized compared to 3.5:7b's ~5.5GB.
            Even with a capable machine, response times with Qwen3.6 noticeably slow with complex tasks, indicating that it may not be ideal for
            all users. It is for this reason that we wish to keep the possibility of switching out models at the user’s behest open. Luckily, a key strength
            of MCP is that scripts written with it are compatible with virtually any model with the right communication tool. For our purposes, Jonathan 
            Gastón Löwenstern's Ollama MCP Bridge serves as this gateway.<footnote>
                <para>Löwenstern's tools for Ollama and MCP communication include both the Ollama MCP Bridge at <link xlink:href="https://github.com/jonigl/ollama-mcp-bridge" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://github.com/jonigl/ollama-mcp-bridge</link> and a terminal interface at 
                    <link xlink:href="https://github.com/jonigl/mcp-client-for-ollama" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://github.com/jonigl/mcp-client-for-ollama</link>.</para>
            </footnote>
                We intend to adapt code used for our Uncertainty Monitor project to allow for model
                switching as a form of customization and future-proofing.<footnote><para>See the Model Registry library python dictionary for our AI Uncertainty Monitor project on at <link xlink:href="https://codeberg.org/newtfire/ai-artsound/src/branch/main/uncertainty-monitor.py#L106" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://codeberg.org/newtfire/ai-artsound/src/branch/main/uncertainty-monitor.py#L106</link>.</para></footnote> As agentic AI becomes more popular, we may see capable, local models at smaller sizes become 
            widely available. Based on current literature on the high potential of SLMs as agents when operating in tandem, we also expect that we can improve performance significantly by pairing an SLM for chat interaction with a second SLM that works as its agent in applying XML stack tools.<footnote><para>See, for example, this helpful article discussing the high potential for SLMs in project workflows: Peter Belcak, Greg Heinrich, Shizhe Diao, Yonggan Fu, Xin Dong, 
                    Saurav Muralidharan, Yingyan Celine Lin, and Pavlo Molchanov, <quote>Small Language Models are the Future of Agentic AI</quote>, Arxiv preprint, under review, September 2025, <link xlink:href="https://arxiv.org/pdf/2506.02153" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">https://arxiv.org/pdf/2506.02153</link>.
                    
            </para></footnote> In addition, our intention to log results systematically may create a valuable resource for fine-tuning and training future variants
            of these local models. They may highlight logical weaknesses and points where the user has to <quote>guide</quote> the model, if any come up.</para>
            
        <para>We expect a few hiccups for developing and deploying Dockerized agents. To work with the MCP agent after deployment requires some technological know-how of Docker and its functions. This can be unintuitive for those in the Digital Humanities community without software development backgrounds.
                For instance, upon composition of an image, Docker creates a sort of interior file system that is not readily accessible by the user through
                a GUI. Customizing the agent within Docker depends on learning how to mount directories: essentially transferring a folder on the user’s system into the container so that the files they 
                wish to work with are available to the agent. This requires a knowledge of filesystems and building or customizing compose.yml files that can be obtuse for 
                many users. Put bluntly: it may seem far easier to load up an LLM service like Claude Desktop and point it where to go. We intend to circumvent
                this by including clear set-up documentation, noting how to establish command line aliases for mounting. For this reason, contemplate the importance of providing easy <quote>on-ramps</quote> through simple, impatient-user-friendly dccumentation, perhaps with interactive web interface guidance to help guide customizations of the system. We have prepared such an interactive local web interface designed for users unfamiliar with the command line for our Uncertainty Monitor project, and contemplate something similar for the DigitAI XML-MCP project.
        </para>
    </section>

    <section>
        <title>Towards a declarative method for working with language models: A separation of concerns</title>
        <para>Declaring one’s intentions is important for language models and humans alike. Writing
            schemas, grammars, and MCP scripts may perhaps all be considered declarations together.
            Declaring intentions leads to specific formulations that depend on the context and scope
            of a project, whether you encode the page by page graphical layout, the relationship
            between an illustration and surrounding text.</para>
        <para>Our DH lab has been working between two different cultures of digital text: the
            documentary markup culture and the natural language processing culture. The operations
            of language models are fascinating for their endless variety of dimensional possibilities
            working over hundreds or thousands of vectors even in an SLM. Yet the availability of
            all those possibilities makes them generate irreproducible results when applied to
            projects where reliability and accuracy are expected. By contrast, traversing XML node
            trees fits more easily in a finite human imagination than hundreds and thousands of
            dimensions. We have powerful capacity to express and define relationships with
            structured markup, so we can deliver meaningful node packages when a project like a
            scholarly edition requires precision and quality control.</para>
        <para>When we bring these two cultures together, declarative markup technologies may be
            helping us to define our terms for controlling and customizing systems for specialized
            projects. Our work with modeling grammars and schemas is definitional, and when we
            instruct an AI agent to apply a validation step and inspect the results before making a
            recommendation, we are then bringing it into a culture whose rules we have carefully
            defined. When the AI works within those parameters, it may then apply its considerable
            powers of generative natural language processing to suggest what is incomplete, or even
            help us to refine our scripts to improve and complete our projects. Our role in
            declaring our parameters is defining the boundaries within which we want AI to work. We
            are defining the terms by which the language model system will function most efficiently
            and reliably within the rule-based architecture that we have declared.</para>
        <para>In course of developing this paper, we have recognized that the old, familiar functional programming
            concept of a <quote>separation of concerns</quote> can guide how we work with language models. Giving a model access to XML, yet keeping the editing of that XML away from that language model’s internal tokenized embedding layers is one separation of processing concerns. Limiting the need and capacity of a language model to
            access one’s operating system is another.</para>
        <para>Perhaps the most important separation of concerns for us to keep in view is the
            education of our communities of practice in refining AI tools to fit our XML tasks,
            rather than letting the tools shape those tasks for us on the terms by which they were
            originally designed. AI in Digital Humanities education should emphasize hands-on
            experimentation, critical evaluation of outputs, and an awareness of when
                <emphasis>not</emphasis> to rely on AI, and when its formidable powers to seek
            associations and define new methods and pathways put us and our computers at risk of
            security hazards. Instead of replacing our existing workflows, perhaps with an
            appropriate separation of concerns, we can see how AI can responsibly and effectively
            operate within the scopes we set. </para>

    </section>
    <section xml:id="xmlmcp-appA" xreflabel="Appendix A">
        <title>Appendix A: A poorly encoded recipe for Syllabub and its Relax NG schema</title>
        <section xml:id="xmlmcp-appA1" xreflabel="Appendix A. 1.">
            <title>A. 1. The Syllabub recipe XML</title>
            <para>This began as a student homework exercise, and represents an amalgamation. <!--of--> </para>
<programlisting xml:space="preserve">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;?xml-model href="../schemas/recipe.rnc" type="application/relax-ng-compact-syntax"?&gt;
&lt;recipe&gt;&lt;healthData&gt;About this recipe Healthiness : (71 votes)&lt;/healthData&gt;
    &lt;!--ebb: Hi This is a comment --&gt;
    &lt;!--ebb 2020-08-27: I like putting initials on my comments, and sometimes the date, 
             especially if multiple people are writing comments on a code file. --&gt;
    &lt;para&gt;The &lt;culture ref="England" monarch="George_III"&gt;Georgians&lt;/culture&gt; loved rich, sweet food. Sugar had become much
        more easily available (mostly because of the Transatlantic Slave Trade) and was fast
        replacing honey as the main food sweetener.&lt;/para&gt;
    &lt;para&gt;This version of the syllabub recipe was by &lt;name type="person"&gt;Eliza Acton&lt;/name&gt;, who
        lived in &lt;timePeriod&gt;18th century&lt;/timePeriod&gt;. There are &lt;altRecipe&gt;plenty of earlier
            versions but they are more likely to curdle as they contain cider&lt;/altRecipe&gt;. This
        version was very modern and fashionable in its day and is easy to manage: &lt;blockQuote&gt;Take a
            quart of cream, a pint of sack, juice of a lemon, whip it, as the froth flies take it
            off with a spoon and lay it in glasses: but first you must sweeten and stir some white
            wine into your glasses, and gently lay on your froth. Set them by and do not make them
            long before you use them.&lt;/blockQuote&gt;
    &lt;/para&gt;
    &lt;para&gt;Sugar and sherry (known as sack) were still expensive ingredients and dishes like this
        would have been eaten in the houses of the richer merchants who would be able to afford
        sugar, lemons, new salad vegetables and sack.&lt;/para&gt;
    &lt;para&gt;We have added a non-alcoholic lemon syllabub for you to try too.&lt;/para&gt;
    &lt;para&gt;For images of the cooking process see our Syllabub Pictures.&lt;/para&gt;
    &lt;para type="credits"&gt;With thanks to &lt;name type="person"&gt;Ian Pycroft&lt;/name&gt; of &lt;name type="organization"&gt;Black Knight Historical&lt;/name&gt; and to &lt;name type="organization"&gt;The
            Georgian House, &lt;name type="place"&gt;Bristol&lt;/name&gt;&lt;/name&gt;.&lt;/para&gt;
    &lt;section kind="ingred"&gt;
        &lt;heading&gt;Ingredients&lt;/heading&gt;
        &lt;list&gt;&lt;item quant="1" unit="fruit"&gt;1 &lt;ingred&gt;lemon&lt;/ingred&gt;&lt;/item&gt;
            &lt;item quant=".25" unit="pint"&gt;1/4 pint &lt;ingred&gt;sack&lt;/ingred&gt; (pale or dark)&lt;/item&gt;
            &lt;item quant="2 3" unit="ounce"&gt;2-3 oz &lt;ingred&gt;caster
                sugar&lt;/ingred&gt;&lt;/item&gt;&lt;!-- This is one way to handle multiple good values in an attribute,
                with quant="2 3": It means quant can be 2 or 3.--&gt;
            &lt;item quant=".5" unit="pint"&gt;1/2 pint &lt;ingred&gt;double cream&lt;/ingred&gt;&lt;/item&gt;
            &lt;item quantLow="4" quantHigh="6" unit="Tb"&gt;4-6 tablespoons &lt;ingred&gt;sweet/dessert white
                    wine&lt;/ingred&gt;
            &lt;/item&gt;
        &lt;/list&gt;
    &lt;/section&gt;
    &lt;section kind="equip"&gt;
        &lt;heading&gt;Equipment&lt;/heading&gt;
        &lt;list&gt;
            &lt;item&gt;Knife&lt;/item&gt;
            &lt;item&gt;Grater&lt;/item&gt;
            &lt;item&gt;Chopping board&lt;/item&gt;
            &lt;item&gt;Mixing bowl&lt;/item&gt;
            &lt;item&gt;Jug&lt;/item&gt;
            &lt;item&gt;Tablespoon&lt;/item&gt;
        &lt;/list&gt;
    &lt;/section&gt;
    &lt;section kind="process"&gt;
        &lt;heading&gt;Making and cooking it&lt;/heading&gt;
        &lt;listStep&gt;
            &lt;step num="1"&gt;Always &lt;action&gt;wash&lt;/action&gt; your hands before preparing food&lt;/step&gt;
            &lt;step num="2"&gt;&lt;action&gt;Grate&lt;/action&gt; half the peel, &lt;action&gt;pare off&lt;/action&gt; the rest
                in fine strips&lt;/step&gt;
            &lt;step num="3"&gt;Place sherry, grated peel, lemon juice and sugar in bowl and
                    &lt;action&gt;soak&lt;/action&gt; for 2 hours&lt;/step&gt;
            &lt;step num="4"&gt;&lt;action&gt;Whip&lt;/action&gt; the cream until semi-stiff&lt;/step&gt;
            &lt;step num="5"&gt;&lt;action&gt;Add&lt;/action&gt; sherry gradually&lt;/step&gt;
            &lt;step num="6"&gt;&lt;action&gt;Spoon&lt;/action&gt; a little wine into glass and spoon on whipped
                cream&lt;/step&gt;
            &lt;step num="7"&gt;&lt;action&gt;Decorate&lt;/action&gt; the top with lemon peel sticks&lt;/step&gt;
            &lt;step num="8"&gt;&lt;action&gt;Serve&lt;/action&gt; with Shrewsberry cakes&lt;/step&gt;
        &lt;/listStep&gt;
    &lt;/section&gt;
&lt;/recipe&gt;  
</programlisting>
         </section>
        <section xml:id="xmlmcp-appA2" xreflabel="Appendix A. 2.">
            <title>A. 2. Relax NG Compact schema for the recipe XML</title>
<programlisting xml:space="preserve">
start = recipe 
recipe = element recipe {healthData, para+, section+}
healthData = element healthData {text}
para = element para {type?, mixed{ (culture | name | timePeriod | altRecipe | blockQuote )*}}
culture = element culture {ref?, monarch?, text }
ref = attribute ref {text}
monarch = attribute monarch {text}
name = element name {type, mixed{name*}}
type= attribute type {"person" | "place" | "organization" | "credits"}
timePeriod = element timePeriod {text}
altRecipe = element altRecipe {text}
blockQuote = element blockQuote {text}
section = element section {kind, heading, (\list | listStep) }
kind = attribute kind { "ingred" | "equip" | "process"}
heading = element heading {text}
\list = element list {item+}
listStep = element listStep {step+}
item = element item {quant?, quantLow?, quantHigh?, unit?, mixed{(ingred)*}}
ingred = element ingred {text}
quant = attribute quant {list{xsd:float+}}
quantLow = attribute quantLow {xsd:float}
quantHigh = attribute quantHigh {xsd:float}
unit = attribute unit {"fruit" | "pint" | "ounce" | "Tb" | "t" | text}
step = element step {num, mixed{(action | ingred)*}}
num = attribute num {xsd:int}
action = element action { text}               
</programlisting>
        </section>
        
    </section>
    <section xml:id="xmlmcp-appB" xreflabel="Appendix B">
        <title>Appendix B: Some examples of Qwen2.5 models poor performance as solo agents</title>
  <para>Here are some examples of poor performance from our smaller Qwen2.5 models. We speculate that perhaps the problem was asking these models to <quote>walk and chew gum at the same time</quote>, 
    that is, in asking the same small Qwen model to engage in conversation and work as code processing agents.</para>
        <section xml:id="xmlmcp-appB1" xreflabel="Appendix B. 1."><title>B. 1. Qwen2.5:1b Conversation Segment</title>
<programlisting xml:space="preserve">

┌─────────────────────────────────────────────────────────────────────────────┐
│                   Welcome to the MCP Client for Ollama �                   │
└─────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────── � Available Tools ─────────────────────────────┐
│ ✓ digitxml.xpath_query                  ✓ digitxml.xquery_query            │
│ ✓ digitxml.xslt_transform               ✓ digitxml.validate_schema         │
│ ✓ digitxml.get_structure_summary        ✓ digitxml.find_irregularities     │
│ ✓ digitxml.apply_transformation         ✓ digitxml.batch_corrections       │
│ ✓ digitxml.create_backup                ✓ digitxml.reload_document         │
└──────────────────────────── 10/10 tools enabled ────────────────────────────┘
┌──────────────────────────────────────┐
│ Current model: qwen2.5:1.5b (ollama) │
│ Capabilities: � Tools               │
└──────────────────────────────────────┘
┌─────────────────────────────── Startup Help ────────────────────────────────┐
│                                                                             │
│ Getting Started:                                                            │
│ • Type /model or /m to select a model                                       │
│ • Type /tools or /t to configure tools                                      │
│ • Type /server:prompt_name to invoke an MCP server prompt                   │
│ • (New!) Type @resource_uri to read a resource or @ for autocomplete        │
│ suggestions                                                                 │
│ • Type /input-mode or /im to switch single-line or multiline chat input     │
│ • Type /clear or /cc to clear conversation context                          │
│ • Type /help or /h to see the full command list                             │
│ • Type /quit or /q to exit the client                                       │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

qwen2.5/10-tools❯ Validate the recipe at "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml" against
 the schema at "F:/GitHub/test/AI Research/digitxml-mcp/schemas/recipe.rnc". Then, using the tools you have availa
ble, write a copy that fixes any errors in the recipe.

(New!) You can press 'a' to abort generation.


┌─────────────────── � Executing Tool digitxml.validate_schema ────────────────────┐
│                                                                                   │
│  Arguments:                                                                       │
│                                                                                   │
│                                                                                   │
│  {                                                                                │
│    "schema_path": "F:/GitHub/test/AI Research/digitxml-mcp/schemas/recipe.rnc",   │
│    "xml_path": "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml"  │
│  }                                                                                │
│                                                                                   │
└───────────────────────────────────────────────────────────────────────────────────┘

�‍� Human-in-the-Loop Confirmation
Tool to execute: digitxml.validate_schema
Arguments:
  • schema_path: F:/GitHub/test/AI Research/digitxml-mcp/schemas...
  • xml_path: F:/GitHub/test/AI Research/digitxml-mcp/data/sy...

Options:
  y/yes - Execute the tool call
  n/no - Skip this tool call
  s/session - Execute without asking for this session
  d/disable - Disable HIL confirmations permanently
  a/abort - Abort this query (won't save to history)

What would you like to do? (y): y
Tip: Use 'human-in-loop' or 'hil' to disable these confirmations

┌────────────────────────────────── ✅ Tool Response digitxml.validate_schema ───────────────────────────────────┐
│                                                                                                                │
│  Arguments:                                                                                                    │
│                                                                                                                │
│                                                                                                                │
│  {                                                                                                             │
│    "schema_path": "F:/GitHub/test/AI Research/digitxml-mcp/schemas/recipe.rnc",                                │
│    "xml_path": "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml"                               │
│  }                                                                                                             │
│                                                                                                                │
│  Response:                                                                                                     │
│                                                                                                                │
│                                                                                                                │
│  {                                                                                                             │
│    "success": true,                                                                                            │
│    "valid": false,                                                                                             │
│    "error_count": 2,                                                                                           │
│    "errors": [                                                                                                 │
│      "F:\\GitHub\\test\\AI Research\\.venv\\Lib\\site-packages\\jingtrang\\__init__.py:5: UserWarning: pkg_re  │
│      "import pkg_resources"                                                                                    │
│    ],                                                                                                          │
│    "schema": "F:\\GitHub\\test\\AI Research\\digitxml-mcp\\schemas\\recipe.rnc",                               │
│    "xml": "F:\\GitHub\\test\\AI Research\\digitxml-mcp\\data\\syllabubRecipe.xml"                              │
│  }                                                                                                             │
│                                                                                                                │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘


(New!) You can press 'a' to abort generation.



� Answer:
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────

The validation process was successful, but there were errors in the schema. Here's a copy of the corrected recipe:

**Original Recipe:**
```xml
&lt;syllabub&gt;
    &lt;name&gt;Syllabub&lt;/name&gt;
    &lt;ingredients&gt;
        &lt;!-- Add ingredients here --&gt;
    &lt;/ingredients&gt;
    &lt;instructions&gt;
        &lt;!-- Add instructions here --&gt;
    &lt;/instructions&gt;
&lt;/syllabub&gt;
```

**Corrected Recipe (with validation errors removed):**
```xml
&lt;syllabub&gt;
    &lt;name&gt;Syllabub&lt;/name&gt;
    &lt;ingredients&gt;
        &lt;ingredient&gt;1 cup of milk&lt;/ingredient&gt;
        &lt;ingredient&gt;2 tablespoons of honey&lt;/ingredient&gt;
        &lt;ingredient&gt;5 tablespoons of egg yolks&lt;/ingredient&gt;
        &lt;ingredient&gt;1/4 teaspoon of salt&lt;/ingredient&gt;
    &lt;/ingredients&gt;
    &lt;instructions&gt;
        &lt;instruction&gt;Add all the ingredients together and mix well.&lt;/instruction&gt;
        &lt;instruction&gt;Mix until the consistency is thick enough to serve as a drink without any additional stirring
or blending needed.&lt;/instruction&gt;
    &lt;/instructions&gt;
&lt;/syllabub&gt;
```

If you want to further apply corrections or validations, please provide more details on what type of corrections or
 additional checks are required.


qwen2.5/10-tools❯ Validate the recipe at "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml" against the schema at "F:/GitHub/test/AI Research/digitxml-mcp/schemas/recipe.rnc". Then, using the tools you have available, write a copy that fixes any errors in the recipe. Do not change the content: ONLY change what the errors indicate to match the schema.

(New!) You can press 'a' to abort generation.


┌──────────────────── � Executing Tool digitxml.validate_schema ────────────────────┐
│                                                                                    │
│  Arguments:                                                                        │
│                                                                                    │
│                                                                                    │
│  {                                                                                 │
│    "xml_path": "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml",  │
│    "schema_path": "F:/GitHub/test/AI Research/digitxml-mcp/schemas/recipe.rnc"     │
│  }                                                                                 │
│                                                                                    │
└────────────────────────────────────────────────────────────────────────────────────┘

�‍� Human-in-the-Loop Confirmation
Tool to execute: digitxml.validate_schema
Arguments:
  • xml_path: F:/GitHub/test/AI Research/digitxml-mcp/data/sy...
  • schema_path: F:/GitHub/test/AI Research/digitxml-mcp/schemas...

Options:
  y/yes - Execute the tool call
  n/no - Skip this tool call
  s/session - Execute without asking for this session
  d/disable - Disable HIL confirmations permanently
  a/abort - Abort this query (won't save to history)

What would you like to do? (y): y
Tip: Use 'human-in-loop' or 'hil' to disable these confirmations

┌──────────────────────────── ✅ Tool Response digitxml.validate_schema ─────────────────────────────┐
│                                                                                                    │
│  Arguments:                                                                                        │
│                                                                                                    │
│                                                                                                    │
│  {                                                                                                 │
│    "xml_path": "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml",                  │
│    "schema_path": "F:/GitHub/test/AI Research/digitxml-mcp/schemas/recipe.rnc"                     │
│  }                                                                                                 │
│                                                                                                    │
│  Response:                                                                                         │
│                                                                                                    │
│                                                                                                    │
│  {                                                                                                 │
│    "success": true,                                                                                │
│    "valid": false,                                                                                 │
│    "error_count": 2,                                                                               │
│    "errors": [                                                                                     │
│      "F:\\GitHub\\test\\AI Research\\.venv\\Lib\\site-packages\\jingtrang\\__init__.py:5: UserWar  │
│      "import pkg_resources"                                                                        │
│    ],                                                                                              │
│    "schema": "F:\\GitHub\\test\\AI Research\\digitxml-mcp\\schemas\\recipe.rnc",                   │
│    "xml": "F:\\GitHub\\test\\AI Research\\digitxml-mcp\\data\\syllabubRecipe.xml"                  │
│  }                                                                                                 │
│                                                                                                    │
└────────────────────────────────────────────────────────────────────────────────────────────────────┘


(New!) You can press 'a' to abort generation.



� Answer:
──────────────────────────────────────────────────────────────────────────────────────────────────────

The validation process was successful, but there were errors in the schema. Here's a copy of the correc
ted recipe:

**Original Recipe:**
```xml
&lt;syllabub&gt;
    &lt;name&gt;Syllabub&lt;/name&gt;
    &lt;ingredients&gt;
        &lt;!-- Add ingredients here --&gt;
    &lt;/ingredients&gt;
    &lt;instructions&gt;
        &lt;!-- Add instructions here --&gt;
    &lt;/instructions&gt;
&lt;/syllabub&gt;
```

**Corrected Recipe (with validation errors removed):**
```xml
&lt;syllabub&gt;
    &lt;name&gt;Syllabub&lt;/name&gt;
    &lt;ingredients&gt;
        &lt;ingredient&gt;1 cup of milk&lt;/ingredient&gt;
        &lt;ingredient&gt;2 tablespoons of honey&lt;/ingredient&gt;
        &lt;ingredient&gt;5 tablespoons of egg yolks&lt;/ingredient&gt;
        &lt;ingredient&gt;1/4 teaspoon of salt&lt;/ingredient&gt;
    &lt;/ingredients&gt;
    &lt;instructions&gt;
        &lt;instruction&gt;Add all the ingredients together and mix well.&lt;/instruction&gt;
        &lt;instruction&gt;Mix until the consistency is thick enough to serve as a drink without any addition
al stirring or blending needed.&lt;/instruction&gt;
    &lt;/instructions&gt;
&lt;/syllabub&gt;
```

Please note that these corrections should match the schema provided, not the original content. If you n
eed further adjustments or additional checks, please provide more details on what type of corrections a
re required.

qwen2.5/10-tools❯ Can you read the file located at "F:/GitHub/test/AI Research/digitxml-mcp/data/sylla
bubRecipe.xml"?

(New!) You can press 'a' to abort generation.


┌───────────────── � Executing Tool digitxml.reload_document ──────────────────┐
│                                                                               │
│  Arguments:                                                                   │
│                                                                               │
│                                                                               │
│  {                                                                            │
│    "path": "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml"  │
│  }                                                                            │
│                                                                               │
└───────────────────────────────────────────────────────────────────────────────┘

�‍� Human-in-the-Loop Confirmation
Tool to execute: digitxml.reload_document
Arguments:
  • path: F:/GitHub/test/AI Research/digitxml-mcp/data/sy...

Options:
  y/yes - Execute the tool call
  n/no - Skip this tool call
  s/session - Execute without asking for this session
  d/disable - Disable HIL confirmations permanently
  a/abort - Abort this query (won't save to history)

What would you like to do? (y): y
Tip: Use 'human-in-loop' or 'hil' to disable these confirmations

┌────────────────── ✅ Tool Response digitxml.reload_document ──────────────────┐
│                                                                               │
│  Arguments:                                                                   │
│                                                                               │
│                                                                               │
│  {                                                                            │
│    "path": "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml"  │
│  }                                                                            │
│                                                                               │
│  Response:                                                                    │
│                                                                               │
│                                                                               │
│  {                                                                            │
│    "success": true,                                                           │
│    "message": "Document reloaded"                                             │
│  }                                                                            │
│                                                                               │
└───────────────────────────────────────────────────────────────────────────────┘


(New!) You can press 'a' to abort generation.



� Answer:
──────────────────────────────────────────────────────────────────────────────────────────────────────

The file located at "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml" has been successf
ully reloaded. It's ready for further processing or editing as needed.

� Answer (Markdown):
──────────────────────────────────────────────────────────────────────────────────────────────────────

The file located at "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml" has been
successfully reloaded. It's ready for further processing or editing as needed.

qwen2.5/10-tools❯ Use digitxml.find_irregularities on the syllabubRecipe file.

(New!) You can press 'a' to abort generation.


┌──────── � Executing Tool digitxml.find_irregularities ─────────┐
│                                                                 │
│  Arguments:                                                     │
│                                                                 │
│                                                                 │
│  {                                                              │
│    "checks": [                                                  │
│      {                                                          │
│        "description": "The name element must have a value.",    │
│        "xpath": "/syllabub/name"                                │
│      },                                                         │
│      {                                                          │
│        "description": "All instructions should contain text.",  │
│        "xquery": "/ingredients/instruction[not(text())]"        │
│      }                                                          │
│    ]                                                            │
│  }                                                              │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

�‍� Human-in-the-Loop Confirmation
Tool to execute: digitxml.find_irregularities
Arguments:
  • checks: [{'description': 'The name element must have a ...

Options:
  y/yes - Execute the tool call
  n/no - Skip this tool call
  s/session - Execute without asking for this session
  d/disable - Disable HIL confirmations permanently
  a/abort - Abort this query (won't save to history)

What would you like to do? (y): y
Tip: Use 'human-in-loop' or 'hil' to disable these confirmations

┌───────── ✅ Tool Response digitxml.find_irregularities ─────────┐
│                                                                 │
│  Arguments:                                                     │
│                                                                 │
│                                                                 │
│  {                                                              │
│    "checks": [                                                  │
│      {                                                          │
│        "description": "The name element must have a value.",    │
│        "xpath": "/syllabub/name"                                │
│      },                                                         │
│      {                                                          │
│        "description": "All instructions should contain text.",  │
│        "xquery": "/ingredients/instruction[not(text())]"        │
│      }                                                          │
│    ]                                                            │
│  }                                                              │
│                                                                 │
│  Response:                                                      │
│                                                                 │
│                                                                 │
│  Input validation error: 'xpath' is a required property         │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘


(New!) You can press 'a' to abort generation.



� Answer:
──────────────────────────────────────────────────────────────────────────────────────────────────────

The function call failed because the `check` property was not provided in the `checks` object. To fix t
his, you need to provide the `description` and `type` properties for each check.

Here's an example of how to modify the `digitxml.find_irregularities` function call:

```json
{
  "id": "df4dc863-ea1d-4811-826e-f0caa1b3e3f6",
  "type": "function",
  "function": {
    "name": "digitxml.find_irregularities",
    "arguments": "{\"checks\": [{\"description\": \"The name element must have a value.\", \"xpath\": \
"/syllabub/name\"}, {\"description\": \"All instructions should contain text.\", \"xquery\": \"/ingredi
ents/instruction[not(text())]\"}]}",
    "additional_properties_required": ["description", "type"]
  }
}
```

This ensures that all required properties are present in the `checks` object. If you need to add more c
hecks, just expand the array accordingly.
</programlisting>
        <para>Above, Qwen2.5:1b hallucinates its own Syllabub recipe file based on the schema, and attempts to change the MCP function call itself instead of 
            the recipe file as requested.</para></section>
        <section xml:id="xmlmcp-appB2" xreflabel="Appendix B. 2.">
            <title>B. 2. Qwen2.5:7b Conversation Segment</title>
<programlisting xml:space="preserve">

┌────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                              Welcome to the MCP Client for Ollama �                               │
└────────────────────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────── � Available Tools ────────────────────────────────────────┐
│ ✓ digitxml.xpath_query            ✓ digitxml.xquery_query           ✓ digitxml.xslt_transform      │
│ ✓ digitxml.validate_schema        ✓ digitxml.get_structure_summary  ✓ digitxml.find_irregularities │
│ ✓ digitxml.apply_transformation   ✓ digitxml.batch_corrections      ✓ digitxml.create_backup       │
│ ✓ digitxml.reload_document                                                                         │
└─────────────────────────────────────── 10/10 tools enabled ────────────────────────────────────────┘
┌────────────────────────────────────┐
│ Current model: qwen2.5:7b (ollama) │
│ Capabilities: � Tools             │
└────────────────────────────────────┘
┌────────────────────────────────── Startup Help ──────────────────────────────────┐
│                                                                                  │
│ Getting Started:                                                                 │
│ • Type /model or /m to select a model                                            │
│ • Type /tools or /t to configure tools                                           │
│ • Type /server:prompt_name to invoke an MCP server prompt                        │
│ • (New!) Type @resource_uri to read a resource or @ for autocomplete suggestions │
│ • Type /input-mode or /im to switch single-line or multiline chat input          │
│ • Type /clear or /cc to clear conversation context                               │
│ • Type /help or /h to see the full command list                                  │
│ • Type /quit or /q to exit the client                                            │
│                                                                                  │
└──────────────────────────────────────────────────────────────────────────────────┘

qwen2.5/10-tools❯ Validate the recipe at "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.
xml" against the schema at "F:/GitHub/test/AI Research/digitxml-mcp/schemas/recipe.rnc". Then, using t
he tools you have available, write a copy that fixes any errors in the recipe. Do not change the conte
nt: ONLY change what the errors indicate to match the schema.

(New!) You can press 'a' to abort generation.


┌─────────────────── � Executing Tool digitxml.validate_schema ────────────────────┐
│                                                                                   │
│  Arguments:                                                                       │
│                                                                                   │
│                                                                                   │
│  {                                                                                │
│    "schema_path": "F:/GitHub/test/AI Research/digitxml-mcp/schemas/recipe.rnc",   │
│    "xml_path": "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml"  │
│  }                                                                                │
│                                                                                   │
└───────────────────────────────────────────────────────────────────────────────────┘

�‍� Human-in-the-Loop Confirmation
Tool to execute: digitxml.validate_schema
Arguments:
  • schema_path: F:/GitHub/test/AI Research/digitxml-mcp/schemas...
  • xml_path: F:/GitHub/test/AI Research/digitxml-mcp/data/sy...

Options:
  y/yes - Execute the tool call
  n/no - Skip this tool call
  s/session - Execute without asking for this session
  d/disable - Disable HIL confirmations permanently
  a/abort - Abort this query (won't save to history)

What would you like to do? (y): y
Tip: Use 'human-in-loop' or 'hil' to disable these confirmations

┌────────────────────────────────────────────────────────────────────────────────── ✅ Tool Response digitxml.validate_schema ──────────────────────────────────────────────────────────────────────────────────┐
│                                                                                                                                                                                                               │
│  Arguments:                                                                                                                                                                                                   │
│                                                                                                                                                                                                               │
│                                                                                                                                                                                                               │
│  {                                                                                                                                                                                                            │
│    "schema_path": "F:/GitHub/test/AI Research/digitxml-mcp/schemas/recipe.rnc",                                                                                                                               │
│    "xml_path": "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml"                                                                                                                              │
│  }                                                                                                                                                                                                            │
│                                                                                                                                                                                                               │
│  Response:                                                                                                                                                                                                    │
│                                                                                                                                                                                                               │
│                                                                                                                                                                                                               │
│  {                                                                                                                                                                                                            │
│    "success": true,                                                                                                                                                                                           │
│    "valid": false,                                                                                                                                                                                            │
│    "error_count": 2,                                                                                                                                                                                          │
│    "errors": [                                                                                                                                                                                                │
│      "F:\\GitHub\\test\\AI Research\\.venv\\Lib\\site-packages\\jingtrang\\__init__.py:5: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. T  │
│      "import pkg_resources"                                                                                                                                                                                   │
│    ],                                                                                                                                                                                                         │
│    "schema": "F:\\GitHub\\test\\AI Research\\digitxml-mcp\\schemas\\recipe.rnc",                                                                                                                              │
│    "xml": "F:\\GitHub\\test\\AI Research\\digitxml-mcp\\data\\syllabubRecipe.xml"                                                                                                                             │
│  }                                                                                                                                                                                                            │
│                                                                                                                                                                                                               │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘


(New!) You can press 'a' to abort generation.



� Answer:
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

The validation process has identified two errors in the XML document "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml" against the schema at "F:/GitHub/test/AI Research/digitxml-mcp/schemas/reci
pe.rnc". The warnings are related to deprecated API usage and do not affect the validation directly. However, there seem to be issues with the XML structure that need addressing.

To proceed, we will write an XSLT transformation to correct these errors based on the provided schema. Let's generate an XSLT stylesheet that can fix those specific errors and then apply it.

I will now create a simple XSLT template to handle the errors identified. Please note that this is a simplified approach; more complex schemas might require more sophisticated handling.


┌─────────────────────────────────────────────────────────────────────────────── � Executing Tool digitxml.apply_transformation ───────────────────────────────────────────────────────────────────────────────┐
│                                                                                                                                                                                                               │
│  Arguments:                                                                                                                                                                                                   │
│                                                                                                                                                                                                               │
│                                                                                                                                                                                                               │
│  {                                                                                                                                                                                                            │
│    "validate": true,                                                                                                                                                                                          │
│    "xslt": "&lt;xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"3.0\"&gt;\n    &lt;xsl:template match=\"/recipe\"&gt;\n        &lt;!-- Handle specific errors here based on the schema --&gt;\n     │
│    "description": "Correction for validation errors in syllabubRecipe.xml"                                                                                                                                    │
│  }                                                                                                                                                                                                            │
│                                                                                                                                                                                                               │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

�‍� Human-in-the-Loop Confirmation
Tool to execute: digitxml.apply_transformation
Arguments:
  • validate: True
  • xslt: &lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/19...
  • description: Correction for validation errors in syllabubRec...

Options:
  y/yes - Execute the tool call
  n/no - Skip this tool call
  s/session - Execute without asking for this session
  d/disable - Disable HIL confirmations permanently
  a/abort - Abort this query (won't save to history)

What would you like to do? (y): y
Tip: Use 'human-in-loop' or 'hil' to disable these confirmations

┌─────────────────────────────────────────────────────────────────────────────── ✅ Tool Response digitxml.apply_transformation ────────────────────────────────────────────────────────────────────────────────┐
│                                                                                                                                                                                                               │
│  Arguments:                                                                                                                                                                                                   │
│                                                                                                                                                                                                               │
│                                                                                                                                                                                                               │
│  {                                                                                                                                                                                                            │
│    "validate": true,                                                                                                                                                                                          │
│    "xslt": "&lt;xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"3.0\"&gt;\n    &lt;xsl:template match=\"/recipe\"&gt;\n        &lt;!-- Handle specific errors here based on the schema --&gt;\n     │
│    "description": "Correction for validation errors in syllabubRecipe.xml"                                                                                                                                    │
│  }                                                                                                                                                                                                            │
│                                                                                                                                                                                                               │
│  Response:                                                                                                                                                                                                    │
│                                                                                                                                                                                                               │
│                                                                                                                                                                                                               │
│  {                                                                                                                                                                                                            │
│    "success": false,                                                                                                                                                                                          │
│    "error": "'saxonche.PySaxonProcessor' object has no attribute 'new_serializer'"                                                                                                                            │
│  }                                                                                                                                                                                                            │
│                                                                                                                                                                                                               │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘


(New!) You can press 'a' to abort generation.



� Answer:
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

It appears that there was an issue with the XSLT transformation process. The error message suggests that there might be a compatibility or version problem with the Saxon processor being used.

To address this, I will generate a more detailed and specific XSLT stylesheet based on the schema to handle the errors identified during validation. This time, let's ensure we are correctly addressing the issue
s found in the XML document.

I'll create an XSLT template that specifically targets the errors mentioned by the validation process. Since we don't have the exact details of the errors, I will assume common issues such as missing or incorre
ct elements/attributes and provide a generic correction.

Let's generate this corrected XSLT:
```xml
&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"&gt;
    &lt;xsl:template match="/"&gt;
        &lt;!-- Handle specific errors here based on the schema --&gt;
        &lt;xsl:apply-templates select="recipe"/&gt;
    &lt;/xsl:template&gt;

    &lt;xsl:template match="recipe"&gt;
        &lt;!-- Add default attributes or elements if missing --&gt;
        &lt;xsl:copy&gt;
            &lt;xsl:attribute name="title" select="'Default Title'"/&gt;
            &lt;xsl:attribute name="prepTime" select="'00:00'"/&gt;
            &lt;xsl:apply-templates/&gt;
        &lt;/xsl:copy&gt;
    &lt;/xsl:template&gt;

    &lt;!-- Add more specific templates as needed --&gt;
&lt;/xsl:stylesheet&gt;
```

Now, I will apply this XSLT to the XML document.

[{"name": "digitxml.apply_transformation", "arguments": {"validate": true, "xslt": "&lt;xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"3.0\"&gt;\n    &lt;xsl:template match=\"/\"&gt;\n        &lt;
!-- Handle specific errors here based on the schema --&gt;\n        &lt;xsl:apply-templates select=\"recipe\"/&gt;\n    &lt;/xsl:template&gt;\n\n    &lt;xsl:template match=\"recipe\"&gt;\n        &lt;!-- Add default attributes or elem
ents if missing --&gt;\n        &lt;xsl:copy&gt;\n            &lt;xsl:attribute name=\"title\" select=\"'Default Title'\"/&gt;\n            &lt;xsl:attribute name=\"prepTime\" select=\"'00:00'\"/&gt;\n            &lt;xsl:apply-templat
es/&gt;\n        &lt;/xsl:copy&gt;\n    &lt;/xsl:template&gt;\n\n    &lt;!-- Add more specific templates as needed --&gt;\n&lt;/xsl:stylesheet&gt;"}]}


qwen2.5/10-tools❯ Can you try that again?

(New!) You can press 'a' to abort generation.



� Answer:
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Sure, let's proceed with the steps to validate and correct the XML document.

First, we'll validate the `syllabubRecipe.xml` against the schema `recipe.rnc`. Then, based on the validation results, I will create a more specific XSLT transformation to fix any errors identified in the XML d
ocument.

Let's start by validating the document:


┌─────────────────────────────────────────────────────┐
│ LLM Error: Extra data: line 1 column 157 (char 156) │
└─────────────────────────────────────────────────────┘

qwen2.5/10-tools❯ Can you try that again?

(New!) You can press 'a' to abort generation.



� Answer:
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Sure, I will proceed with the validation and apply the corrections based on the schema. Let's validate the XML document first to identify any errors.

I'll start by validating the "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml" against the schema at "F:/GitHub/test/AI Research/digitxml-mcp/schemas/recipe.rnc".

Let's execute this validation.


┌─────────────────── � Executing Tool digitxml.validate_schema ────────────────────┐
│                                                                                   │
│  Arguments:                                                                       │
│                                                                                   │
│                                                                                   │
│  {                                                                                │
│    "schema_path": "F:/GitHub/test/AI Research/digitxml-mcp/schemas/recipe.rnc",   │
│    "xml_path": "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml"  │
│  }                                                                                │
│                                                                                   │
└───────────────────────────────────────────────────────────────────────────────────┘

�‍� Human-in-the-Loop Confirmation
Tool to execute: digitxml.validate_schema
Arguments:
  • schema_path: F:/GitHub/test/AI Research/digitxml-mcp/schemas...
  • xml_path: F:/GitHub/test/AI Research/digitxml-mcp/data/sy...

Options:
  y/yes - Execute the tool call
  n/no - Skip this tool call
  s/session - Execute without asking for this session
  d/disable - Disable HIL confirmations permanently
  a/abort - Abort this query (won't save to history)

What would you like to do? (y): y
Tip: Use 'human-in-loop' or 'hil' to disable these confirmations

┌────────────────────────────────────────────────────────────────────────────────── ✅ Tool Response digitxml.validate_schema ──────────────────────────────────────────────────────────────────────────────────┐
│                                                                                                                                                                                                               │
│  Arguments:                                                                                                                                                                                                   │
│                                                                                                                                                                                                               │
│                                                                                                                                                                                                               │
│  {                                                                                                                                                                                                            │
│    "schema_path": "F:/GitHub/test/AI Research/digitxml-mcp/schemas/recipe.rnc",                                                                                                                               │
│    "xml_path": "F:/GitHub/test/AI Research/digitxml-mcp/data/syllabubRecipe.xml"                                                                                                                              │
│  }                                                                                                                                                                                                            │
│                                                                                                                                                                                                               │
│  Response:                                                                                                                                                                                                    │
│                                                                                                                                                                                                               │
│                                                                                                                                                                                                               │
│  {                                                                                                                                                                                                            │
│    "success": true,                                                                                                                                                                                           │
│    "valid": false,                                                                                                                                                                                            │
│    "error_count": 2,                                                                                                                                                                                          │
│    "errors": [                                                                                                                                                                                                │
│      "F:\\GitHub\\test\\AI Research\\.venv\\Lib\\site-packages\\jingtrang\\__init__.py:5: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. T  │
│      "import pkg_resources"                                                                                                                                                                                   │
│    ],                                                                                                                                                                                                         │
│    "schema": "F:\\GitHub\\test\\AI Research\\digitxml-mcp\\schemas\\recipe.rnc",                                                                                                                              │
│    "xml": "F:\\GitHub\\test\\AI Research\\digitxml-mcp\\data\\syllabubRecipe.xml"                                                                                                                             │
│  }                                                                                                                                                                                                            │
│                                                                                                                                                                                                               │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘


(New!) You can press 'a' to abort generation.



� Answer:
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

It seems there is a warning related to the `pkg_resources` package, but this does not affect the validation of our XML document against the schema. The key information here is that the XML document has two erro
rs according to the schema.

Let's proceed with creating an XSLT transformation based on these errors to correct them automatically. Based on typical issues we might encounter, I'll create a more detailed XSLT stylesheet that addresses com
mon validation problems such as missing required attributes or elements.

Here’s a generic XSLT template for corrections:

```xml
&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"&gt;
    &lt;xsl:template match="/"&gt;
        &lt;!-- Handle specific errors here based on the schema --&gt;
        &lt;xsl:apply-templates select="recipe"/&gt;
    &lt;/xsl:template&gt;

    &lt;xsl:template match="recipe"&gt;
        &lt;!-- Add default attributes or elements if missing --&gt;
        &lt;xsl:copy&gt;
            &lt;xsl:attribute name="title" select="'Default Title'"/&gt;
            &lt;xsl:attribute name="prepTime" select="'00:00'"/&gt;
            &lt;xsl:apply-templates/&gt;
        &lt;/xsl:copy&gt;
    &lt;/xsl:template&gt;

    &lt;!-- Add more specific templates as needed --&gt;
&lt;/xsl:stylesheet&gt;
```

I will apply this XSLT to the XML document using `digitxml.apply_transformation`.

[{"name": "digitxml.apply_transformation", "arguments": {"validate": true, "xslt": "&lt;xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"3.0\"&gt;\n    &lt;xsl:template match=\"/\"&gt;\n        &lt;
!-- Handle specific errors here based on the schema --&gt;\n        &lt;xsl:apply-templates select=\"recipe\"/&gt;\n    &lt;/xsl:template&gt;\n\n    &lt;xsl:template match=\"recipe\"&gt;\n        &lt;!-- Add default attributes or elem
ents if missing --&gt;\n        &lt;xsl:copy&gt;\n            &lt;xsl:attribute name=\"title\" select=\"'Default Title'\"/&gt;\n            &lt;xsl:attribute name=\"prepTime\" select=\"'00:00'\"/&gt;\n            &lt;xsl:apply-templat
es/&gt;\n        &lt;/xsl:copy&gt;\n    &lt;/xsl:template&gt;\n\n    &lt;!-- Add more specific templates as needed --&gt;\n&lt;/xsl:stylesheet&gt;"}]}

qwen2.5/10-tools❯ Go ahead and use the digitxml.apply_transformation script.

(New!) You can press 'a' to abort generation.


┌─────────────────────────────────────────────────────────────────────────────── � Executing Tool digitxml.apply_transformation ───────────────────────────────────────────────────────────────────────────────┐
│                                                                                                                                                                                                               │
│  Arguments:                                                                                                                                                                                                   │
│                                                                                                                                                                                                               │
│                                                                                                                                                                                                               │
│  {                                                                                                                                                                                                            │
│    "xslt": "&lt;xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"3.0\"&gt;\n    &lt;xsl:template match=\"/\"&gt;\n        &lt;!-- Handle specific errors here based on the schema --&gt;\n        &lt;  │
│    "validate": true                                                                                                                                                                                           │
│  }                                                                                                                                                                                                            │
│                                                                                                                                                                                                               │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

�‍� Human-in-the-Loop Confirmation
Tool to execute: digitxml.apply_transformation
Arguments:
  • xslt: &lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/19...
  • validate: True

Options:
  y/yes - Execute the tool call
  n/no - Skip this tool call
  s/session - Execute without asking for this session
  d/disable - Disable HIL confirmations permanently
  a/abort - Abort this query (won't save to history)

What would you like to do? (y): y
Tip: Use 'human-in-loop' or 'hil' to disable these confirmations

┌─────────────────────────────────────────────────────────────────────────────── ✅ Tool Response digitxml.apply_transformation ────────────────────────────────────────────────────────────────────────────────┐
│                                                                                                                                                                                                               │
│  Arguments:                                                                                                                                                                                                   │
│                                                                                                                                                                                                               │
│                                                                                                                                                                                                               │
│  {                                                                                                                                                                                                            │
│    "xslt": "&lt;xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"3.0\"&gt;\n    &lt;xsl:template match=\"/\"&gt;\n        &lt;!-- Handle specific errors here based on the schema --&gt;\n        &lt;  │
│    "validate": true                                                                                                                                                                                           │
│  }                                                                                                                                                                                                            │
│                                                                                                                                                                                                               │
│  Response:                                                                                                                                                                                                    │
│                                                                                                                                                                                                               │
│                                                                                                                                                                                                               │
│  {                                                                                                                                                                                                            │
│    "success": false,                                                                                                                                                                                          │
│    "error": "'saxonche.PySaxonProcessor' object has no attribute 'new_serializer'"                                                                                                                            │
│  }                                                                                                                                                                                                            │
│                                                                                                                                                                                                               │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘


� Answer:
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

It seems there was an issue with the Saxon processor, specifically that it does not have the `new_serializer` method available. This could be due to a version mismatch or other compatibility issues.

Let's try another approach to correct the XML document using a more straightforward XSLT transformation. We will add default attributes and elements as placeholders where necessary based on common schema requir
ements.

Here is an updated XSLT template:

```xml
&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"&gt;
    &lt;xsl:template match="/"&gt;
        &lt;!-- Handle specific errors here based on the schema --&gt;
        &lt;xsl:apply-templates select="recipe"/&gt;
    &lt;/xsl:template&gt;

    &lt;xsl:template match="recipe"&gt;
        &lt;!-- Add default attributes or elements if missing --&gt;
        &lt;xsl:copy&gt;
            &lt;xsl:attribute name="title" select="'Default Title'"/&gt;
            &lt;xsl:attribute name="prepTime" select="'00:00'"/&gt;
            &lt;xsl:apply-templates/&gt;
        &lt;/xsl:copy&gt;
    &lt;/xsl:template&gt;

    &lt;!-- Add more specific templates as needed --&gt;
&lt;/xsl:stylesheet&gt;
```

Let's apply this XSLT to the XML document.

[{"name": "digitxml.apply_transformation", "arguments": {"validate": true, "xslt": "&lt;xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"3.0\"&gt;\n    &lt;xsl:template match=\"/\"&gt;\n        &lt;
!-- Handle specific errors here based on the schema --&gt;\n        &lt;xsl:apply-templates select=\"recipe\"/&gt;\n    &lt;/xsl:template&gt;\n\n    &lt;xsl:template match=\"recipe\"&gt;\n        &lt;!-- Add default attributes or elem
ents if missing --&gt;\n        &lt;xsl:copy&gt;\n            &lt;xsl:attribute name=\"title\" select=\"'Default Title'\"/&gt;\n            &lt;xsl:attribute name=\"prepTime\" select=\"'00:00'\"/&gt;\n            &lt;xsl:apply-templat
es/&gt;\n        &lt;/xsl:copy&gt;\n    &lt;/xsl:template&gt;\n\n    &lt;!-- Add more specific templates as needed --&gt;\n&lt;/xsl:stylesheet&gt;"}]}
</programlisting>
        <para>Qwen2.5:7b, despite not receiving any workable feedback on what is wrong with the recipe file, suggests running (incomplete) XSLT.</para></section>
    </section>

</article>