MCP Testing
Overview
MCP server testing covers metadata validation, tool wiring, instance isolation, domain scoping, backward compatibility, docs-loader behavior, docs-chat routing, and Docusaurus SSE parsing. The core MCP/docs search suite is split across these files:
- MCP server tests:
tests/shared/unit/mcp-servers/mcp-servers.test.ts-- 41 tests across 9 server describe blocks - DocsIndexer tests:
tests/shared/unit/docs-search/indexer-class.test.ts-- 19 tests for the DocsIndexer class
The focused MCP/docs-chat validation run also includes docs loader, docs-chat agent/route, Docusaurus hook, and SSE parser tests. Current recorded evidence: 6 files and 73 tests passed.
Test Suite: MCP Servers
File: tests/shared/unit/mcp-servers/mcp-servers.test.ts
Structure
The test file is organized into 8 MCP server describe blocks plus one
registry metadata integration block:
| Describe Block | Tests | Server |
|---|---|---|
| K12 Safety MCP Server | 5 | createK12SafetyMcpServer() |
| Reasoning Engine MCP Server | 4 | createReasoningEngineMcpServer() |
| Admin MCP Server | 4 | createAdminMcpServer() |
| Docs MCP Server | 5 | createDocsMcpServer() |
| K12 Docs MCP Server | 6 | createK12DocsMcpServer() |
| SDAC Docs MCP Server | 3 | createSdacDocsMcpServer() |
| TAP Docs MCP Server | 3 | createTapDocsMcpServer() |
| RE Docs MCP Server | 3 | createReasoningEngineDocsMcpServer() |
| Server info integration | 8 | Registry metadata across the MCP factories |
What Is Tested
Each server describe block validates:
- Metadata -- Server name, version, and description match expected values
- Tool wiring -- The correct number of tools are registered and their IDs match the expected set
- Instance isolation -- Calling the factory twice returns two independent instances (no shared state)
- Domain scoping (docs servers only) -- The indexer is scoped to the correct subdirectory
- Backward compatibility -- Server names and versions have not changed unexpectedly (semver contract)
Mocking Strategy
The MCPServer class is mocked with a stub that captures constructor arguments:
// Simplified mock pattern
vi.mock('@mastra/mcp', () => ({
MCPServer: vi.fn().mockImplementation((config) => ({
config,
})),
}));
This allows tests to verify the arguments passed to the MCPServer constructor without needing a real MCP runtime. The mock captures:
config.name-- Server identifierconfig.version-- Semver version stringconfig.description-- Human-readable descriptionconfig.tools-- The tool registry object (verified by checking keys)
Example Test Pattern
describe('Admin MCP Server', () => {
it('should have correct metadata', () => {
const server = createAdminMcpServer();
expect(server.config.name).toBe('Admin MCP Server');
expect(server.config.version).toBe('1.0.0');
});
it('should wire all expected admin tools', () => {
const server = createAdminMcpServer();
const toolIds = Object.keys(server.config.tools);
expect(toolIds).toHaveLength(EXPECTED_ADMIN_TOOL_COUNT);
expect(toolIds).toContain('admin-update-llm-params');
expect(toolIds).toContain('admin-db-health-check');
// ... remaining tool assertions
});
it('should return independent instances', () => {
const server1 = createAdminMcpServer();
const server2 = createAdminMcpServer();
expect(server1).not.toBe(server2);
});
});
Test Suite: DocsIndexer
File: tests/shared/unit/docs-search/indexer-class.test.ts
What Is Tested
The DocsIndexer test suite covers 19 tests across these areas:
- Index construction -- Verifies that
.mdxfiles are parsed and indexed correctly - Search functionality -- Tests full-text search with boosting, prefix matching, and fuzzy matching
- Domain scoping -- Verifies that indexers scoped to subdirectories only index files within their scope
- Concurrent safety -- Tests that concurrent
buildIndex()calls share a single promise - Refresh behavior -- Verifies that
docs-refresh-indexrebuilds the index from scratch - Content truncation -- Tests that content beyond
MAX_CONTENT_LENGTH(8000 chars) is truncated - Frontmatter parsing -- Verifies extraction of title, description, and other metadata
Runtime Verification
Beyond unit tests, MCP servers can be verified at runtime by starting the development server and checking the discovery endpoints.
Step 1: Start the Dev Server
npm run dev
Step 2: Check Discovery Metadata
curl http://localhost:4111/mcp-servers.json
Expected output: JSON metadata for all registered MCP servers with their names,
versions, and tool counts. The audited runtime route exposes
/mcp-servers.json; it does not expose a separate /mcp-servers HTML
directory.
Step 3: Verify Individual Server
Use an MCP client or deployment-verified transport URL to check a specific server. The source-backed registry proves the server IDs and metadata, while the exact HTTP/SSE transport paths are owned by the Mastra runtime/APIM deployment layer and should be smoke-tested in the target environment.
For local stdio validation of the docs MCP servers, use the committed launcher and smoke script. This is the preferred Replit/client setup path because it uses the real MCP client transport and keeps stdout reserved for protocol messages.
npm run docs:mcp:smoke -- --server docs
npm run docs:mcp:smoke -- --server sdac-docs
npm run docs:mcp:smoke -- --server k12-docs
npm run docs:mcp:smoke -- --server tap-docs
npm run docs:mcp:smoke -- --server reasoning-engine-docs
npm run docs:mcp:smoke -- --all
For the trusted-collaborator diagnostics workbench MCP, validate the local stdio adapter and generated internal context bundle with:
npm run diagnostics:workbench:smoke
After the testing diagnostics control-plane image is deployed, validate the hosted streamable HTTP endpoint with a diagnostics token:
DIAGNOSTICS_TOKEN_CODEX=<diagnostics token> npm run diagnostics:workbench:smoke -- \
--remote-url https://test-aitools-llfc-diagnostics.azurewebsites.net/mcp \
--token-env DIAGNOSTICS_TOKEN_CODEX
The hosted diagnostics workbench endpoint is /mcp on the diagnostics control
plane, not an APIM /ai/api/mcp/{serverId}/mcp runtime route.
Step 4: Test via VS Code
- Configure a local MCP client entry for the server URL you want to test
- Open VS Code with the Copilot extension
- Invoke an MCP tool through the Copilot chat interface
- Verify the tool executes and returns expected results
Adding Tests for a New Server
When adding a new MCP server, follow this template to add tests:
// In tests/shared/unit/mcp-servers/mcp-servers.test.ts
describe('New Domain MCP Server', () => {
it('should have correct metadata', () => {
const server = createNewDomainMcpServer();
expect(server.config.name).toBe('New Domain MCP Server');
expect(server.config.version).toBe('1.0.0');
expect(server.config.description).toBeDefined();
});
it('should wire all expected tools', () => {
const server = createNewDomainMcpServer();
const toolIds = Object.keys(server.config.tools);
expect(toolIds).toHaveLength(EXPECTED_TOOL_COUNT);
// Assert each tool ID explicitly
for (const expectedId of EXPECTED_TOOL_IDS) {
expect(toolIds).toContain(expectedId);
}
});
it('should return independent instances', () => {
const a = createNewDomainMcpServer();
const b = createNewDomainMcpServer();
expect(a).not.toBe(b);
});
});
Checklist for New Server Tests
- Add a new
describeblock inmcp-servers.test.ts - Test metadata (name, version, description)
- Test tool wiring with explicit tool ID assertions
- Test instance isolation
- If a docs server, test domain scoping via indexer path
- Update the test count in this documentation
Troubleshooting
Tests fail with "Cannot find module"
The MCP server factories import from tool registries. If a tool file was moved or renamed, the import path in the factory file may be stale. Check src/mastra/mcp-servers/*.ts for broken imports.
Tool count mismatch
If a test expects N tools but the server has N+1, a new tool was added to the domain's tool registry without updating the test assertion. Add the new tool ID to the expected list in the test.
Instance isolation test fails
If two factory calls return the same object reference, the factory is caching its result. MCP server factories must create a new MCPServer instance on every call -- check for module-level caching in the factory file.
Indexer tests fail on CI
The DocsIndexer reads .mdx files from the filesystem. On CI, the working directory may differ from local development. Ensure the test setup sets the correct rootPath relative to the project root.
Code Locations
- MCP server tests:
tests/shared/unit/mcp-servers/mcp-servers.test.ts - DocsIndexer tests:
tests/shared/unit/docs-search/indexer-class.test.ts - Server factories under test:
src/mastra/mcp-servers/*.ts - Tool registries under test:
src/mastra/tools/*/index.ts