Skip to main content

MCP Server for Technical Docs

This recipe defines an end-to-end architecture for making structured technical documentation—originally authored in Heretto CCMS — discoverable, contextual, and actionable by AI agents like ChatGPT, Perplexity, or custom assistants. It combines the strengths of Conscia’s Core Services, DX Graph, Hybrid Search, and DX Engine orchestration, all exposed through a unified Model Context Protocol (MCP) Server. The goal is to implement a real-time, agent-native retrieval flow—where content is indexed using both keyword and vector search, enriched at query time with graph relationships, ranked using business rules (and optionally LLMs), and delivered to agents in a structured, consumable format. This approach supports RAG techniques like Vector-RAG, Graph-RAG, and Tool-RAG, empowering LLMs to not just find content, but understand and reason over it—securely and at scale.

At the heart of this approach is the recognition that structured content is a prerequisite for intelligent, AI-driven retrieval. Formats like DITA XML are not just publishing frameworks—they encode meaning, relationships, topic types, and intent. That structure gives your content machine-understandable semantics: enabling RAG (Retrieval-Augmented Generation) techniques to identify whether a topic is a task, concept, or reference; to resolve prerequisites; and to follow RELATED or CONCEPT_OF links—all without training a model on your domain from scratch.


Why export content into DX Graph?

Exporting Heretto’s structured DITA topics into DX Graph turns static documentation into a live, multi-domain knowledge fabric that your search, chat, and commerce experiences can explore in real time.

  • Cross-domain linking: Join docs to SKUs, support issues, personas, and any third-party data—well beyond Heretto’s own reltables.
  • Graph queries at speed: DX Graph answers relationship-heavy queries in less than 50 ms. Deploy API was never built for that load.
  • Hybrid RAG ready: Blend keyword + vector search with on-the-fly graph enrichment, giving LLMs richer context.
  • Delivery decoupled from authoring: Content teams keep writing in Heretto; delivery teams tune retrieval rules in DX Engine—no CMS changes.
  • Governance & observability: Core-Services Jobs, Triggers, and audit logs provide retries, metrics, and policy enforcement.
  • Easy downstream syndication: Same graph feed can power analytics, help centers, or partner portals via export jobs.

In short, Heretto remains the single source of truth, while DX Graph becomes the high-performance, relationship-aware runtime that unlocks personalization, RAG accuracy, and cross-system reuse.

1 Building‑Block Cheat‑Sheet

LayerProduct / ServicePurpose
AuthoringHeretto CCMS (DITA topics & maps)Writers craft structured technical docs.
ExportHeretto Deploy APIStreams JSON/DITA OT bundles on every Publish.
Data OpsConscia Core ServicesJobs, Buckets, Triggers, Integration Patterns for ETL in/out of DX Graph.
GraphDX GraphUnified KG: tech docs, products, relationships.
SearchOpenSearch (keyword + vector)Hybrid BM‑25 + dense‑vector retrieval.
FlowDX Engine discover.docs.ragOrchestrates search → graph → ranking (+optional LLM).
API GatewayUniversal MCP ServerPublishes capability discoverDocs; proxies to DX Engine.
Agent / UIChatGPT, website chat, voice bot, etc.Calls discoverDocs and renders enriched answers.

2 Ingestion Pipeline (Core‑Services)

StepCore‑Services ComponentAction
A1Incoming BucketNightly Heretto JSON dump (dita_*.json) lands in heretto-dumps (S3/Azure).
A2importDataFiles JobCron 0 2 * * * parses each file → writes records to dita-topics collection in DX Graph.
A3Transform Job (optional)transformDataFiles normalises metadata, maps Heretto IDs to product SKUs.
A4DX Graph EventDataRecordCreated/Updated event emitted for each topic.
A5Trigger ➜ callDxEngine JobTrigger ditaUpdated calls DX Engine template dita-to-opensearch to: ① enrich with related entities ② embed body text ③ upsert doc in OpenSearch.
A6Integration Pattern 2.1If external systems need change notifications, event stream can hit a webhook or Kafka topic.
A7Scheduled Export (optional)exportCollection → downstream lake / BI via processCollectionWithWebserviceEndpoint.

Example Job & Trigger

// importDataFiles Job (runs nightly)
{
"jobDefinitionCode": "dita-import",
"jobType": "importDataFiles",
"schedule": { "cron": "0 2 * * *" },
"params": {
"incomingBucketCode": "heretto-dumps",
"processedBucketCode": "processed",
"invalidBucketCode": "invalid",
"filenamePattern": "dita_*.json",
"recordIdentifierField": "topicId",
"collectionCode": "dita-topics"
}
}

// Trigger → DX Engine
{
"eventType": "DataRecordUpdated",
"triggerCode": "ditaUpdated",
"criteria": "`event.data.dataCollectionCode === 'dita-topics'`",
"job": {
"jobType": "callDxEngine",
"params": {
"templateCode": "dita-to-opensearch",
"context": "`event`"
}
}
}

3 Heretto Deploy API Cheat‑Sheet

ItemDetail
Base URLhttps://deploy.<org‑id>.heretto.com/api/v2/
AuthX-API-Key: <key> (Simple Key) or Authorization: Bearer <token>
Full MapGET /deployments/{depId}/maps/{mapId}?locale=en-US&depth=all&format=json
Single TopicGET /deployments/{depId}/topics/{topicId}?locale=en-US&format=json
Delta FeedGET /deployments/{depId}/delta?modifiedSince=2025-07-26T00:00:00Z
CachingResponses are prerendered & server‑cached → safe for CDN.

4 Runtime Discovery Algorithm

discoverDocs(q, k) ───► DX Flow discover.docs.rag
① hybridSearch(OpenSearch, q, k) // BM25 + vector
② for each hit ➜ DX Graph lookup(id) // RELATED, PREREQUISITE, etc.
③ scoring
base = 0.6*bm25 + 0.4*vector
+10 if topicType == 'Task'
+2 per RELATED edge 'Troubleshooting'
LLM‑rerank top 20 (optional)
④ return top N enriched docs

Business rules live in DX Engine; change weights or filters without code deploys.


5 Architecture Diagram


6 End‑to‑End Sequence

#ActorAction
1Heretto PublishWriters release a new map; Deploy API JSON lands in bucket.
2Job dita-importParses file; upserts topics into DX Graph.
3Graph Event → TriggerditaUpdated fires callDxEngine job.
4DX Engine FlowEnriches doc, embeds text, indexes in OpenSearch.
5AgentCalls discoverDocs({q, k}) via UMCP.
6OpenSearchReturns top k keyword+vector hits.
7DX Graph LookupGraph‑augment step fetches relations per hit.
8DX Engine Rules EngineApplies rules / LLM re‑rank; returns enriched list.
9Agent LLMCrafts conversational answer & follow‑ups.

7 Orchestration Flow Design for Search Ranking

#Component (type)Key configPurpose
AUniversal API – search-osMethod = POST /opensearch/_searchHybrid keyword + vector query.
BObject Mapper – mapHitshits.hits[*] → $.hits[]Extract id, bm25Score, vectorScore, topicType.
CFor-Each Loop – enrichHitsIterate over $.hits[]Drives per-hit graph look-up.
  C1  Universal API – graphLookupPath /collections/dita-topics/records/{{hit.id}}?include=relatedPull RELATED / PREREQUISITE edges.
  C2  Data-Transformation Script – mergeGraphJS snippet (see below)Append related[] to the hit object.
DData-Transformation Script – scoreHitsJS scoring logic0.6 × bm25 + 0.4 × vector + rule boosts.
E(Optional) LLM Scorer – llmRerankModel gpt-4o-miniRe-orders top 20 JSON docs.
FObject Mapper – responseMapMap to MCP schemaFinal payload for UMCP.

8 Key Component Configurations

A Universal API search-os

method: POST
url: https://search.acme.io/opensearch/_search
headers:
Content-Type: application/json
bodyTemplate: |
{
"size": {{variables.k}},
"query": {
"hybrid": {
"query": "{{variables.q}}",
"vector": "{{variables.q | embed 'text-embedding-3'}}"
}
},
"_source": ["title","topicType"]
}
responsePath: "$.hits"
timeoutMs: 200

B Object Mapper mapHits

mappings:
- path: "$.hits.hits[*]"
to: "$.hits[]"
fields:
id: "$._id"
title: "$._source.title"
topicType: "$._source.topicType"
bm25Score: "$._score.keyword"
vectorScore: "$._score.vector"

C1 Universal API graphLookup

method: GET
url: https://graph.conscia.ai/collections/dita-topics/records/{{item.id}}
params:
include: related
responsePath: "$"
timeoutMs: 100

C2 · Data Transformation Script mergeGraph

ctx.item.related = ctx.api.related || [];
return ctx.item;

D · Data Transformation Script scoreHits

function ruleBoost(hit){
let b = 0;
if (hit.topicType === 'Task') b += 10;
if (hit.related.some(r => r.edge === 'Troubleshooting')) b += 2;
return b;
}
ctx.hits.forEach(h => {
h.baseScore = 0.6*h.bm25Score + 0.4*h.vectorScore;
h.score = h.baseScore + ruleBoost(h);
});
ctx.hits.sort((a,b) => b.score - a.score);
ctx.hits = ctx.hits.slice(0, ctx.variables.k);
return ctx.hits;

E · LLM Scorer llmRerank

enabled: "{{ variables.k <= 20 && variables.useLLM === true }}"
model: gpt-4o-mini
prompt: |
Rank the following JSON docs by relevance to "{{variables.q}}".
Return the docs in the same JSON shape, sorted best → worst.
input: "{{ json ctx.hits }}"

F · Object Mapper responseMap

mappings:
- path: "$.hits[*]"
to: "$.hits[]"
fields:
id: "$.id"
title: "$.title"
score: "$.score"
topicType: "$.topicType"
related: "$.related"

9 · Flow Variables

VariableSourceUsed by
qUMCP requestComponent A
kUMCP request (default 10)A, D
hits[]Mapper mapHitsLoop C, Scripts D & E
useLLMUMCP flag (bool)LLM Scorer

10 · Live Tuning

  • Weights & boosts live in scoreHits — change them in the console; no redeploy.
  • Search backend swap — just update search-os URL/body.
  • Disable LLM — set useLLM:false in the UMCP request.

7 · Universal MCP Server Stub

paths:
/discoverDocs:
post:
summary: Hybrid tech‑doc discovery
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
q:
type: string
description: Natural‑language query
k:
type: integer
description: Max hits
default: 10
responses:
"200":
description: Enriched docs
content:
application/json:
schema:
$ref: '#/components/schemas/DocHitList'

8 · Implementation Hints

  • Scalability – Core‑Services Jobs are stateless → run in parallel pods optimizing data ingestion performance;
  • Latency Targets – Keep LLM re‑rank to top 20 docs only. Aim for less than 200 ms p95.
  • Versioning – Name capability paths /v1/discoverDocs so future schema changes won’t break agents.
  • Monitoring – Core‑Services exposes Job execution logs, retries, and Trigger audit trails—pipe them to Grafana/Datadog or use Conscia's Observability dashboard.

✅ Result

A fully governed, end‑to‑end pipeline that:

  1. Automates ingestion of Heretto DITA exports via Core‑Services Jobs & Buckets.
  2. Enriches & embeds topics in DX Engine then indexes them in OpenSearch.
  3. Serves hybrid, graph‑aware search through a single Universal MCP Server capability (discoverDocs).
  4. Empowers agents & UIs to deliver rich, context‑aware technical answers—in milliseconds.