case study · Design + AI Tooling
DARIA: An AI Bridge Between Writers and the CMS
Our tech writers were spending more time fighting CMS plumbing than writing - so I built an AI bridge between their editor and the CMS, shipped it to the team in six weeks of UAT-driven iteration, and collapsed the busywork around finding and assembling content.
DARIA sits between the writer's AI editor and the systems the work already lives in: the CMS, Figma, Jira, and Confluence
DARIA - Documentation And Research Intelligence Assistant; from the Old Persian daraya: to maintain, to possess.
The Situation
The Webex technical writing team authors content in DITA XML - a structured documentation standard - managed inside an enterprise CMS. The daily workflow was entirely manual and sequential: gather requirements scattered across Jira, Figma, and Confluence, then hand-code DITA XML in Oxygen XML Editor, visually inspect it for errors, upload files one-by-one through the CMS tree UI, and manually tag taxonomy categories by clicking through a hierarchy. Every stage waited on the one before it - four or more platform switches just to publish a single topic.
The pain wasn't any one tool - it was the accumulated friction, and most of it lived upstream of the writing itself. Before a writer could touch a word of content, they had to hunt down the requirement in Jira, cross-reference the design in Figma, dig up the spec in Confluence, then find the right existing topic buried in the CMS asset tree. Writers are content experts, but the mechanical overhead of information retrieval, context-switching, and CMS navigation diluted that expertise into busywork. New writers faced a steep ramp just to learn the tooling, let alone the content domain.
Meanwhile, Anthropic had released the Model Context Protocol (MCP) - an open standard that lets AI models interact with external tools and data sources. The CMS vendor had published an official MCP server that auto-generates several hundred tools from its full API spec. It was a useful API reference, but several hundred undifferentiated tools is a lot of context for an LLM to reason over, and it didn't support the single sign-on our production CMS required.
My Role & Scope
- Role: Design engineer - product concept, architecture, implementation, packaging, documentation, UAT facilitation, and rollout.
- Team context: Webex Technical Writing org, working alongside content developers and back-end engineers. The content developers were my users, my testers, and my feedback loop.
- Duration: First commit Feb 17, 2026 → GA May 12, 2026. The core was working in about two weeks; the remaining time was ~6 weeks of rapid iteration driven by user acceptance testing.
- Stack: TypeScript, Node.js, MCP SDK, Zod, fast-xml-parser; Python/Flask for a thin internal AI proxy. Ships as DARIA, an installable package writers run locally inside their own AI editor.
The Approach
Framing the problem as a design problem
The official vendor MCP server took the "expose everything" approach - auto-generate a tool for every API endpoint and let the LLM figure it out. That's technically complete but experientially poor. An LLM with several hundred tools is like a user facing a UI with several hundred buttons. It works, but it doesn't guide anyone toward the right action, and it burns context the model needs for the actual task.
I framed this as an interaction design problem: what does a technical writer's actual day look like, and what's the minimum set of tools that covers that workflow end to end? The answer was a curated surface - ~21 purpose-built tools organized around the authoring lifecycle, plus 3 gateway meta-tools that provide escape-hatch access to the full API when something falls outside the common path.
Before - the traditional content workflow: manual, sequential, one person does everything
After - the agentic content workflow: writer-directed, AI-executed, human-gated at every stage
Curated tools over auto-generated sprawl
The curated surface maps directly to what writers do across the authoring lifecycle, organized by function:
- Discovery & navigation - find content without clicking through a folder tree in a separate CMS client. This is where the biggest time savings came from: the retrieval-and-synthesis step that used to eat a writer's morning.
- Read & understand - read DITA source and pull full map bundles. The LLM can then explain the content structure to a new writer in plain English, which turned out to be one of the most compelling onboarding use cases.
- Author & validate - an offline validator (no CMS connection needed) with an autofix mode that normalizes DOCTYPEs, tags, and terminology before validating, plus a markdown-to-DITA converter that emits house-compliant DITA with the correct DOCTYPE and attribute domains, so writers stop hand-coding XML entirely.
- Write & publish - checkout, write, and check-in handled as a single atomic operation with automatic undo-on-failure, so a botched write never leaves an asset locked.
- Taxonomy - the AI analyzes content against the CMS taxonomy schema and recommends categories with reasoning, replacing a tedious manual click-through tagging step.
- CMS gateway - a discover-then-invoke pattern that exposes the full CMS API through the same authenticated session. The curated tools handle ~95% of workflows; nothing is unreachable.
Bridging four systems, not just the CMS
The pivotal insight from watching writers work was that the CMS was only half the problem. The other half was the gathering - pulling the Jira ticket, reading the Figma spec, checking the Confluence page. So DARIA grew from a CMS connector into a true bridge across all four systems a writer touches:
- The CMS - the local MCP server (browse / search / read / write DITA)
- Figma - design context, screenshots, frame names, UI strings, annotations
- Jira - requirements, acceptance criteria, bugs
- Confluence - specs and background docs
The Context Bridge - DARIA sits between the four enterprise sources and whatever AI editor the writer already uses
This is what turned the tool from "a faster way to edit XML" into "the place a writer assembles all their context." A writer can now say "Run the feature doc workflow for [TICKET-ID]" and the agent pulls the ticket, traverses the linked Figma frames, reads the Confluence spec, finds the affected DITA topics in the CMS, and proposes a documentation plan - all before anyone writes a sentence.
A human-gated workflow, not an autopilot
The feature-doc-agent workflow is deliberately gated. The agent retrieves sources, synthesizes a feature summary and a persona-aware user journey, and proposes a plan - then stops and waits for an explicit "Yes, proceed." before generating any DITA. Updates to existing topics are additive by default (new step, new note, new list item - never silent deletion), wrapped in <draft-comment> review markers attributed to the authenticated user, and left checked out for human review in Oxygen before anything is checked in or sent to preview. The writer stays in control of every consequential action; the agent removes the mechanical toil around it.
The gated workflow: read-only browsing, parallel subagents checking candidates, and a human gate. Nothing is applied to the taxonomy until you approve specific values.
The payoff: a ranked recommendation with confidence, category, path, and a reason for each, plus an explicit list of categories it would not apply. Example data shown, not real categories.
Meeting writers where they already are
MCP is client-agnostic by design, so DARIA works in whatever editor a writer already uses: VS Code + GitHub Copilot, OpenAI Codex, Cursor, and Claude Code, each auto-discovering the local servers via its own config file. I also built a thin Python/Flask proxy so the same editors could run against an internal enterprise LLM service, and validated a fully local Ollama path. The local-model path mattered politically: it proved the entire workflow could run air-gapped on a laptop with open-weight models. For a security-conscious enterprise, that changes the conversation.
The Build
Core stack: TypeScript on Node.js, @modelcontextprotocol/sdk for the protocol layer, zod for schema validation (with z.coerce.number() and string-tolerant booleans for compatibility with smaller local models), and fast-xml-parser for the offline DITA validator.
Architecture: A single McpServer instance registers tools conditionally by mode (read-only / author / admin). Each tool is its own module under src/tools/ with a Zod schema and handler. The REST client centralizes all auth methods and session management. The CMS gateway loads endpoint definitions from JSON bundled out of the official MIT-licensed npm package, so it tracks the live API without me maintaining several hundred hand-written tools.
Key technical decisions:
- Deterministic content pipeline - the markdown-to-DITA conversion and offline autofix produce house-compliant DITA every time, instead of trusting an LLM to remember the right DOCTYPE and attribute domains.
- Atomic edits with safe failure - a write is checkout→write→checkin in one call; it undoes the checkout on write failure, and on checkin failure it intentionally leaves the asset checked out so the writer can retry rather than losing work.
- Convention encoding -
.github/copilot-instructions.mdand the per-client agent files encode Webex DITA naming conventions, Cisco style rules, and anti-patterns (likework-in-progressattributes that silently break publishing transforms), so the LLM follows team conventions automatically.
How UAT shaped the product
The six weeks of UAT weren't a validation rubber-stamp - they're visible in the version history. Real writer feedback drove Confluence integration, the Figma REST proxy for Codex, auth-resilience fixes for tokens expiring mid-session, the mcp:doctor health check (because writers couldn't self-diagnose), friendlier package folder names, and the README rewrite separating "do once" from "every session." A feedback CTA is even baked into the agent's workflow milestones, so the loop kept running after rollout. The tool got easier with each iteration because the people breaking it were the people I built it for.
Outcomes
Shipped and GA (May 12, 2026): DARIA - a production package writers install in their own editor, bridging the CMS, Figma, Jira, and Confluence. ~21 curated tools + 3 gateway meta-tools, a deterministic markdown→DITA pipeline, an offline validator with autofix, the gated feature-doc-agent workflow, multi-client support (VS Code Copilot, Codex, Cursor, Claude Code), and a local Ollama path.
- Concentrated the savings upstream - in the information retrieval and synthesis work that used to consume the front half of any documentation task
- Adopted by the writing team as part of how the work gets done, not a pilot a few enthusiasts used
- Ongoing, rapid iteration post-GA, driven by the same feedback loop that built it
- Built in-house - the integration was built internally against the same CMS and the same API, with AI capabilities the previous toolchain didn't offer
Qualitative: the taxonomy recommendation feature - AI analyzing content against the CMS schema and suggesting categories with reasoning - drew the strongest reaction from writing managers. The onboarding use case (the agent explaining unfamiliar DITA structure in plain English) was the one new writers latched onto fastest.
Reflection
The biggest lesson was that the interaction design of an AI tool surface matters as much as the technical integration - several hundred auto-generated tools is technically correct and experientially wrong, the API equivalent of dumping every menu option onto one toolbar. But the lesson that actually moved the needle was watching where the real time went: the win wasn't faster XML editing, it was collapsing the gathering - Jira, Figma, Confluence, CMS - into one conversation. I'd thought I was building a CMS connector; the team taught me, through six weeks of UAT, that I was building a context bridge. If I'd started by shadowing their full day instead of starting at the CMS boundary, I'd have arrived there a couple weeks sooner.