CXA MCP Server
Model Context Protocol server for CX Assurance – exposes an AI-accessible performance tool that lets any MCP-compatible agent (GitHub Copilot, Claude, Cursor, etc.) run real browser-based performance scans and receive a rich dashboard report.
---
Table of Contents
- Overview
- Architecture
- Project Structure
- Available Tools
- Getting Started
- Configuration
- Running the Server
- Testing
- Adding New Tool Categories
- MCP Client Configuration
- Logging
- Sample Performance Payload
---
Overview
The CXA MCP Server is a self-contained performance scanning engine powered by Puppeteer. An agent can ask _"Run a performance scan on https://example.com"_ and receive a rich Markdown dashboard covering:
- Core Web Vitals – Load time, Speed Index (fixed – never negative), TTFB, FCP, DOM Content Loaded, Transfer Size
- Performance grades – A+ through F per Web Vitals thresholds
- Visual load bars – ASCII progress bars for quick visual comparison
- Omni-channel results – Real load times across 6 browser/device profiles with per-profile grades
- Mobile vs Desktop comparison – Average load time delta and % slower
- Actionable recommendations – Targeted suggestions based on actual metric values
Scope: Performance only. Accessibility, SEO, and security data are intentionally excluded from this tool. No external API is called – all scanning is done locally with a real Chromium browser.
---
Architecture
Agent (Copilot / Claude / Cursor …)
│
│ JSON-RPC 2.0 (stdio)
▼
┌─────────────────────────────┐
│ MCP Server (stdio) │
│ src/server.js │
│ │
│ ┌──────────────────────┐ │
│ │ Tool Registry │ │ ← src/tools/index.js
│ │ performanceTool.js │ │ ← src/tools/performanceTool.js
│ └──────────┬───────────┘ │
│ │ │
│ ┌──────────▼───────────┐ │
│ │ Service Layer │ │ ← src/services/performanceService.js
│ └──────────┬───────────┘ │
│ │ orchestrates │
│ ┌──────────▼───────────┐ │
│ │ Scanners │ │ ← loadTimeScanner + performanceScanner only
│ └──────────┬───────────┘ │
│ │ │
│ ┌──────────▼───────────┐ │
│ │ Browser Runner │ │ ← Puppeteer / Chromium
│ └──────────────────────┘ │
└─────────────────────────────┘
│ headless Chromium
▼
Target Web Page
Key design decisions:
| Concern | Decision | |---------|----------| | Transport | stdio – required by the MCP spec for local server ↔ agent communication | | Logging | Always stderr – stdout is reserved for the JSON-RPC transport | | Tool isolation | Each domain (performance, accessibility …) lives in its own file | | No external HTTP library | Node ≥ 18 native fetch – keeps the dependency list minimal | | Error handling | All tool handlers return structured error text instead of throwing, so the agent always receives a readable response | | Scope | Performance-only – accessibility, SEO, security scanners exist but are not wired into cxa_scan_performance |
---
Project Structure
mcp-cxa/
├── .env.example # Environment variable template
├── .gitignore
├── package.json
├── README.md # ← you are here
│
├── performance-samples/ # Reference data & API docs
│ ├── performance_result.json
│ └── performance-details.md
│
├── src/
│ ├── server.js # Entry point – bootstraps MCP server
│ ├── config/
│ │ └── index.js # Centralised config (env-driven)
│ ├── tools/
│ │ ├── index.js # Central tool registry
│ │ └── performanceTool.js # Performance MCP tool definitions
│ ├── services/
│ │ └── performanceService.js # Business logic / API calls
│ └── utils/
│ ├── logger.js # Structured stderr logger
│ ├── httpClient.js # fetch wrapper with timeout & error handling
│ └── formatters.js # Raw payload → Markdown report
│
└── tests/
├── config/
│ └── index.test.js
├── services/
│ └── performanceService.test.js
└── utils/
├── formatters.test.js
└── logger.test.js
---
Available Tools
cxa_scan_performance
Runs a real browser-based performance scan for any URL and returns a rich Markdown dashboard.
| Parameter | Type | Required | Default | Description | |-----------|--------|----------|----------|-------------| | url | string | ✅ | – | Fully-qualified URL to scan | | region | string | ❌ | Local | Label stamped on the report |
Returns: Rich Markdown performance dashboard including:
- Score card with grades (A+–F) for load time, TTFB, FCP
- ASCII visual load bars
- Omni-channel table (6 profiles: Chrome, Edge, Firefox, Safari, Android Chrome, iOS Safari)
- Mobile vs Desktop comparison
- Actionable recommendations
Note: Accessibility, SEO, and security are not included in this tool's output.
---
Getting Started
Prerequisites
- Node.js ≥ 18.0.0 (for native
fetchand--testrunner) - Chromium / Puppeteer (installed automatically via
npm install)
Install
cd mcp-cxa
npm install
Configure
cp .env.example .env
# Edit .env if needed – no API key required
---
Configuration
All configuration is read from environment variables (see .env.example):
| Variable | Default | Description | |-----------------------|-----------|-------------| | CXA_SCAN_TIMEOUT_MS | 30000 | Page load timeout per profile (ms) | | CXA_HEADLESS | true | Set false to watch Chromium during dev | | CXA_DEFAULT_REGION | Local | Region label stamped on results | | CXA_LOG_LEVEL | info | debug / info / warn / error |
No
CXA_API_BASE_URLorCXA_API_TOKENare needed – all scanning is self-contained.
---
Running the Server
# Production
npm start
# Development (auto-restart on file change – Node ≥ 18.11)
npm run dev
Note: The server communicates over stdio. You should not see any output on stdout; all log lines appear on stderr as newline-delimited JSON.
---
Testing
Tests use Node's built-in test runner (node:test) – no additional test framework required.
# Run all tests once
npm test
# Run tests in watch mode
npm run test:watch
Test coverage by module
| Module | Test file | |--------|-----------| | src/config/index.js | tests/config/index.test.js | | src/utils/logger.js | tests/utils/logger.test.js | | src/utils/formatters.js | tests/utils/formatters.test.js | | src/services/performanceService.js | tests/services/performanceService.test.js |
The HTTP client and MCP tool wiring are tested indirectly through the service tests (the HTTP client is stubbed so no real network calls are made).
---
Adding New Tool Categories
The server is designed to grow. To add, say, an Accessibility tool:
- Create the service
src/services/accessibilityService.js
Export getAccessibilitySummary(projectId) and any other methods.
- Create the tool file
src/tools/accessibilityTool.js
Export registerAccessibilityTools(server) following the same pattern as performanceTool.js.
- Register it in the central registry
// src/tools/index.js
const { registerAccessibilityTools } = require('./accessibilityTool');
// ...
function registerAllTools(server) {
registerPerformanceTools(server);
registerAccessibilityTools(server); // ← add this line
}
- Add a formatter (optional) in
src/utils/formatters.js.
- Write tests under
tests/services/andtests/utils/.
---
MCP Client Configuration
VS Code (GitHub Copilot)
Add the following to your VS Code settings.json or .vscode/mcp.json:
{
"servers": {
"cxa-mcp": {
"type": "stdio",
"command": "node",
"args": ["${workspaceFolder}/mcp-cxa/src/server.js"],
"env": {
"CXA_LOG_LEVEL": "info"
}
}
}
}
Claude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"cxa-mcp": {
"command": "node",
"args": ["/absolute/path/to/mcp-cxa/src/server.js"],
"env": {
"CXA_LOG_LEVEL": "info"
}
}
}
}
---
Logging
All log entries are written to stderr as newline-delimited JSON:
{"timestamp":"2026-03-13T06:27:31.123Z","level":"INFO","message":"CXA MCP Server is running – listening on stdio"}
{"timestamp":"2026-03-13T06:27:32.456Z","level":"INFO","message":"Tool invoked: cxa_scan_performance","meta":{"url":"https://example.com","region":"Local"}}
Set CXA_LOG_LEVEL=debug to see every browser navigation event.
---
Sample Performance Payload
The backend returns a JSON object of the following shape (see performance-samples/performance_result.json):
{
"url": "https://www.sammonsfinancialgroup.com/",
"executionId": "464a1bd3-45c8-4390-a31a-5ef779e81ca1",
"timestamp": "2026-03-13T06:27:31.820822Z",
"browser": "Chrome",
"region": "Virginia",
"speedIndex": "0.02 s",
"uiux": "",
"sustainabilityScore": "",
"accessibility": "",
"seoScore": "",
"security": "",
"omniChannel": [
{ "Browser": "Windows 11 - Chrome", "loadTime": 1229, "version": "125" },
{ "Browser": "Android 14 - Chrome", "loadTime": 2058, "version": "14" }
]
}
The formatter converts this into a structured Markdown table report that agents can render or summarise for end users.
---
API Endpoint Reference
| Method | Path | Description | |--------|------|-------------| | GET | /test/reports/getSummaryDetails?projectId=<id> | Fetch latest scan summary | | POST | /test/scan/trigger | Trigger a new scan _(extend when live)_ |






