Skip to main content
Glama
README.md
# 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

1. [Overview](#overview)
2. [Architecture](#architecture)
3. [Project Structure](#project-structure)
4. [Available Tools](#available-tools)
5. [Getting Started](#getting-started)
6. [Configuration](#configuration)
7. [Running the Server](#running-the-server)
8. [Testing](#testing)
9. [Adding New Tool Categories](#adding-new-tool-categories)
10. [MCP Client Configuration](#mcp-client-configuration)
11. [Logging](#logging)
12. [Sample Performance Payload](#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 `fetch` and `--test` runner)
- Chromium / Puppeteer (installed automatically via `npm install`)

### Install

```bash
cd mcp-cxa
npm install
```

### Configure

```bash
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_URL` or `CXA_API_TOKEN` are needed – all scanning is self-contained.

---

## Running the Server

```bash
# 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.

```bash
# 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:

1. **Create the service**

   ```
   src/services/accessibilityService.js
   ```

   Export `getAccessibilitySummary(projectId)` and any other methods.

2. **Create the tool file**

   ```
   src/tools/accessibilityTool.js
   ```

   Export `registerAccessibilityTools(server)` following the same pattern as `performanceTool.js`.

3. **Register it in the central registry**

   ```js
   // src/tools/index.js
   const { registerAccessibilityTools } = require('./accessibilityTool');
   // ...
   function registerAllTools(server) {
     registerPerformanceTools(server);
     registerAccessibilityTools(server);   // ← add this line
   }
   ```

4. **Add a formatter** (optional) in `src/utils/formatters.js`.

5. **Write tests** under `tests/services/` and `tests/utils/`.

---

## MCP Client Configuration

### VS Code (GitHub Copilot)

Add the following to your VS Code `settings.json` or `.vscode/mcp.json`:

```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`)

```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:

```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`):

```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)_ |

TDQS

A4.2/5.0

Scored across 1 tool

Disambiguation5/5

There is only one tool, so there is no risk of selecting the wrong tool or confusing it with another operation. Its purpose is clearly stated as a performance-only scan.

Naming Consistency5/5

The single tool name cxa_scan_performance uses a clear snake_case verb_noun pattern consistent with MCP naming conventions. With no other tools, there is no inconsistency to assess.

Tool Count3/5

A single tool feels thin for a server surface, even though the scope is narrowly defined as performance scanning. It borders on under-scoped but is defensible for a very specific, single-purpose scanner.

Completeness4/5

The tool covers performance measurement across multiple browser/device profiles and returns a rich dashboard, matching the stated performance-only scope. Minor gaps exist around configuration, historical comparison, or export options, but core performance scanning is complete.

Maintenance

ActivityInactive
ResponsivenessNo issues