Skip to main content

Domain Docs MCP Servers

Overview

The platform provides four per-domain documentation search MCP servers, each scoped to a specific subdirectory of the Docusaurus documentation tree. All four servers share the same architecture, using a generic createDomainDocsServer() factory and domain-scoped DocsIndexer instances.

Shared Architecture

All domain docs servers are implemented in src/mastra/mcp-servers/domain-docs-server.ts using a single generic factory function. Each server gets:

  1. A DocsIndexer instance scoped to a specific subdirectory
  2. A set of tools created by createScopedDocsTools() from src/mastra/tools/docs-search/create-scoped-tools.ts
  3. Tool descriptions that include the domain label for clarity

Server Inventory

ServerFactorySubdirectoryDomain LabelVersion
K12 DocscreateK12DocsMcpServer()k12/externalk121.0.0
SDAC DocscreateSdacDocsMcpServer()sdac/externalsdac1.0.0
TAP DocscreateTapDocsMcpServer()tap/internaltap1.0.0
RE DocscreateReasoningEngineDocsMcpServer()reasoning-enginereasoning-engine1.0.0

All four servers share the same skip flag: MASTRA_SKIP_DOCS_MCP.

Tool Registry (Per Server)

Each domain docs server exposes the same 4 tool IDs, scoped to its domain. The tool IDs are identical across servers but unique within each MCP server scope:

Tool IDDescription
docs-searchFull-text search scoped to the domain's documentation subdirectory
docs-listList all indexed pages within the domain's subdirectory
docs-get-pageRetrieve the full content of a page by path (within domain scope)
docs-refresh-indexForce a rebuild of the domain-scoped in-memory search index

Tool descriptions automatically include the domain label to help MCP clients distinguish between servers. For example, the K12 server's docs-search tool description might read: "Search K12 documentation pages."

Generic Factory Implementation

// src/mastra/mcp-servers/domain-docs-server.ts
import { join } from 'node:path';
import { MCPServer } from '@mastra/mcp';
import { DocsIndexer } from '../tools/docs-search/indexer.ts';
import { createScopedDocsTools } from '../tools/docs-search/create-scoped-tools.ts';
import { resolveDocsRoot } from '../tools/shared/docs/resolve-docs-root.ts';

interface DomainDocsConfig {
name: string;
description: string;
subdir: string;
domainLabel: string;
}

function createDomainDocsServer(config: DomainDocsConfig): MCPServerWithIndexer {
const rootPath = join(resolveDocsRoot(), config.subdir);
const indexer = new DocsIndexer(rootPath, { domainLabel: config.domainLabel });
const tools = createScopedDocsTools(indexer, config.domainLabel);

const server = new MCPServer({
name: config.name,
version: '1.0.0',
description: config.description,
tools,
});

// Attach indexer for eager startup build
(server as MCPServerWithIndexer)._indexer = indexer;

return server as MCPServerWithIndexer;
}

// Convenience factory exports
export const createK12DocsMcpServer = () =>
createDomainDocsServer({
name: 'K12 Docs MCP Server',
description: 'Full-text search over K12 external documentation.',
subdir: 'k12/external',
domainLabel: 'k12',
});

export const createSdacDocsMcpServer = () =>
createDomainDocsServer({
name: 'SDAC Docs MCP Server',
description: 'Full-text search over SDAC external documentation.',
subdir: 'sdac/external',
domainLabel: 'sdac',
});

// TAP and RE follow the same pattern...

Use the committed stdio launcher and smoke script when validating these servers for a local agent client:

npm run mcp:docs:start -- sdac-docs
npm run docs:mcp:smoke -- --server sdac-docs

DocsIndexer Class Details

The DocsIndexer class (from src/mastra/tools/docs-search/indexer.ts) is the core component shared by all docs servers.

Constructor

class DocsIndexer {
constructor(rootPath: string, options?: { domainLabel?: string });
}
  • rootPath: Absolute or relative path to the documentation subdirectory to index
  • domainLabel: Optional override for the domain label. If not provided, the domain is auto-detected from the first path segment of the root path

Key Behaviors

  • Eager index build: When a domain docs server is created, the DocsIndexer begins building its index immediately. The _indexer property on the MCPServer instance holds the reference.
  • Concurrent-safe promise sharing: If buildIndex() is called while a build is already in progress, the second call awaits the same promise rather than starting a duplicate build.
  • Domain scoping: The indexer only scans .mdx files within its configured rootPath. This ensures each domain server's search results are isolated to its own documentation.

MCPServerWithIndexer Type

The domain docs servers use an extended type to attach the indexer instance:

type MCPServerWithIndexer = MCPServer & { _indexer: DocsIndexer };

This allows the composition layer to access the indexer for health checks or manual refresh operations.

Scoped Tools Factory

The createScopedDocsTools(indexer, domainLabel) function in src/mastra/tools/docs-search/create-scoped-tools.ts creates the 4 tools wired to a specific DocsIndexer instance:

export function createScopedDocsTools(
indexer: DocsIndexer,
domainLabel: string,
): Record<string, Tool> {
return {
'docs-search': createDocsSearchTool(indexer, domainLabel),
'docs-list': createDocsListTool(indexer, domainLabel),
'docs-get-page': createDocsGetPageTool(indexer, domainLabel),
'docs-refresh-index': createDocsRefreshIndexTool(indexer, domainLabel),
};
}

Each tool function receives the DocsIndexer instance via closure, so all operations (search, list, get, refresh) operate on the same scoped index.

As with the global docs server, scoped docs tool output schemas are top-level objects for MCP discovery compatibility. docs-get-page uses a success boolean plus optional content/error fields rather than a top-level discriminated union.

Implementation Notes

Single Skip Flag

All four domain docs servers (plus the global docs server) are controlled by the single MASTRA_SKIP_DOCS_MCP flag. There is no per-domain skip flag for documentation servers. If you need to disable docs search for one domain but not others, modify the docs artifact loader that attaches scoped docs MCP servers rather than the src/mastra/mcp-servers/index.ts barrel export.

Subdirectory Conventions

The subdirectory paths follow the Docusaurus documentation structure:

  • k12/external -- Public-facing K12 documentation
  • sdac/external -- Public-facing SDAC documentation
  • tap/internal -- Internal TAP documentation (note: "internal" in the path, not "external")
  • reasoning-engine -- Reasoning engine documentation (top-level, no external/internal split)

No Database Dependencies

Like the global docs server, domain docs servers have no database dependencies. They are purely filesystem-based with in-memory indexing.

Code Locations

  • Generic factory: src/mastra/mcp-servers/domain-docs-server.ts
  • Scoped tools factory: src/mastra/tools/docs-search/create-scoped-tools.ts
  • Indexer class: src/mastra/tools/docs-search/indexer.ts
  • Tests: tests/shared/unit/mcp-servers/mcp-servers.test.ts (domain docs describe blocks)
  • Indexer tests: tests/shared/unit/docs-search/indexer-class.test.ts