Skip to main content
Glama

Crownpeak DQM MCP Server

A portable Model Context Protocol (MCP) server that wraps the Crownpeak DQM CMS REST API. This server exposes agent-friendly tools for quality checking, asset management, checkpoint monitoring, and more.

Features

  • Complete API Coverage: All 15 DQM API endpoints implemented and tested

  • Dual Transport Support: Run as stdio (desktop clients) or HTTP server (cloud hosting)

  • Production Ready: TypeScript, error handling, rate limiting, request timeouts

  • Docker Native: Containerized deployment with health checks

  • Portable: Deploy anywhere - AWS, Azure, GCP, Netlify, Vercel, Fly.io, Kubernetes

  • Safe by Default: Read-only operations by default, destructive tools behind feature flag

  • Agent Optimized: Task-oriented tools designed for AI agents

  • Fully Tested: 100% integration test coverage against live DQM API

Quick Start

Prerequisites

  • Node.js 20+

  • npm (included with Node.js)

  • Crownpeak DQM API key

Installation

# Clone repository git clone <repository-url> cd crownpeak-dqm-node-mcp # Install dependencies npm install # Copy environment template cp .env.example .env # Edit .env and add your API key # DQM_API_KEY=your_api_key_here

Build

npm run build

Usage

Local Stdio Mode (Desktop Clients)

For use with desktop MCP clients like Claude Desktop:

# Run directly npm start # Or with environment variables DQM_API_KEY=your_key npm start

Claude Desktop Configuration

Add to your Claude Desktop configuration file:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

Windows: %APPDATA%\Claude\claude_desktop_config.json

{ "mcpServers": { "crownpeak-dqm": { "command": "node", "args": ["/absolute/path/to/crownpeak-dqm-node-mcp/dist/index.js"], "env": { "DQM_API_KEY": "your_api_key_here" } } } }

Claude Desktop Usage Examples

Once configured, you can use natural language to interact with the DQM API through Claude:

Example 1: Quality Check a Website

"Get the content from https://www.crownpeak.com and test it against DQM for quality issues"

Claude will:

  1. Use run_quality_check with your website ID and the URL

  2. Create an asset in DQM

  3. Retrieve and display all quality issues found

Example 2: Check Spelling on a Page

"Run a spellcheck on https://www.example.com using my DQM website"

Claude will:

  1. Use spellcheck_asset to check the URL

  2. Report any misspellings found

Example 3: Review Quality Issues

"Show me all the quality checkpoints configured for my website and then check the homepage against them"

Claude will:

  1. List your websites with list_websites

  2. List checkpoints with list_checkpoints

  3. Run a quality check on your homepage

  4. Present a detailed report

Example 4: Asset Management

"Search for all assets from www.crownpeak.com in my DQM account and show me the ones with the most issues"

Claude will:

  1. Search assets with search_assets

  2. Get issues for each with get_asset_issues

  3. Sort and present the results

Example 5: Get Highlighted Content

"Get the HTML content for asset [ID] with all quality issues highlighted"

Claude will:

  1. Use get_asset_pagehighlight to get highlighted HTML

  2. Display the content with issues marked

HTTP Server Mode (Cloud Hosting)

For remote hosting and API access:

# Start HTTP server npm run start:http # Server will start on port 3000 (configurable via PORT env var)

Test endpoints:

# Health check curl http://localhost:3000/healthz # List available tools curl http://localhost:3000/tools # Call a tool curl -X POST http://localhost:3000/call \ -H "Content-Type: application/json" \ -d '{ "tool": "list_websites", "arguments": {} }'

Docker Deployment

# Create .env file with your API key echo "DQM_API_KEY=your_api_key_here" > .env # Start the server docker-compose up -d # View logs docker-compose logs -f # Stop the server docker-compose down

Using Docker Directly

# Build the image docker build -t crownpeak-dqm-mcp . # Run the container docker run -d \ --name crownpeak-dqm-mcp \ -p 3000:3000 \ -e DQM_API_KEY=your_api_key_here \ crownpeak-dqm-mcp # View logs docker logs -f crownpeak-dqm-mcp # Stop the container docker stop crownpeak-dqm-mcp

Cloud Deployment

AWS

AWS ECS/Fargate

# Build and push to ECR aws ecr create-repository --repository-name crownpeak-dqm-mcp docker tag crownpeak-dqm-mcp:latest <account-id>.dkr.ecr.<region>.amazonaws.com/crownpeak-dqm-mcp:latest docker push <account-id>.dkr.ecr.<region>.amazonaws.com/crownpeak-dqm-mcp:latest # Create task definition with: # - Image: <ecr-url> # - Port: 3000 # - Environment: DQM_API_KEY (use Secrets Manager) # - Health check: /healthz # Deploy using ECS console or CLI

AWS App Runner

# Use App Runner with ECR source # Configure: # - Port: 3000 # - Health check: /healthz # - Environment variable: DQM_API_KEY

Azure

Azure Container Instances

az container create \ --resource-group myResourceGroup \ --name crownpeak-dqm-mcp \ --image crownpeak-dqm-mcp:latest \ --dns-name-label crownpeak-dqm \ --ports 3000 \ --environment-variables DQM_API_KEY=your_key \ --cpu 1 --memory 0.5

Azure Container Apps

az containerapp create \ --name crownpeak-dqm-mcp \ --resource-group myResourceGroup \ --environment myEnvironment \ --image crownpeak-dqm-mcp:latest \ --target-port 3000 \ --ingress external \ --env-vars DQM_API_KEY=secretref:dqm-api-key

GCP

Cloud Run

# Build and push to GCR gcloud builds submit --tag gcr.io/<project-id>/crownpeak-dqm-mcp # Deploy to Cloud Run gcloud run deploy crownpeak-dqm-mcp \ --image gcr.io/<project-id>/crownpeak-dqm-mcp \ --platform managed \ --region us-central1 \ --allow-unauthenticated \ --set-env-vars DQM_API_KEY=your_key \ --port 3000

GKE (Kubernetes)

apiVersion: apps/v1 kind: Deployment metadata: name: crownpeak-dqm-mcp spec: replicas: 2 selector: matchLabels: app: crownpeak-dqm-mcp template: metadata: labels: app: crownpeak-dqm-mcp spec: containers: - name: crownpeak-dqm-mcp image: gcr.io/<project-id>/crownpeak-dqm-mcp:latest ports: - containerPort: 3000 env: - name: DQM_API_KEY valueFrom: secretKeyRef: name: dqm-secrets key: api-key livenessProbe: httpGet: path: /healthz port: 3000 readinessProbe: httpGet: path: /healthz port: 3000 --- apiVersion: v1 kind: Service metadata: name: crownpeak-dqm-mcp spec: type: LoadBalancer ports: - port: 80 targetPort: 3000 selector: app: crownpeak-dqm-mcp

Vercel

Create vercel.json:

{ "version": 2, "builds": [ { "src": "dist/http.js", "use": "@vercel/node" } ], "routes": [ { "src": "/(.*)", "dest": "dist/http.js" } ], "env": { "DQM_API_KEY": "@dqm-api-key" } }

Deploy:

vercel --prod

Netlify

Create netlify.toml:

[build] command = "npm run build" publish = "dist" [functions] node_bundler = "esbuild" [[redirects]] from = "/*" to = "/.netlify/functions/server" status = 200

Create serverless function wrapper in netlify/functions/server.ts.

Fly.io

Create fly.toml:

app = "crownpeak-dqm-mcp" primary_region = "iad" [build] dockerfile = "Dockerfile" [env] PORT = "3000" [[services]] internal_port = 3000 protocol = "tcp" [[services.ports]] port = 80 handlers = ["http"] [[services.ports]] port = 443 handlers = ["tls", "http"] [[services.http_checks]] interval = 10000 timeout = 2000 grace_period = "5s" method = "get" path = "/healthz"

Deploy:

fly launch fly secrets set DQM_API_KEY=your_key fly deploy

Available Tools

Discovery

  • list_websites: List all websites in your DQM account

  • get_website: Get details of a specific website

Checkpoints (Quality Rules)

  • list_checkpoints: List all quality checkpoints, optionally filtered by website

  • get_checkpoint: Get details of a specific checkpoint

Assets (Scanned Pages)

  • search_assets: Search for assets with optional filters

  • get_asset: Get details of a specific asset

  • get_asset_status: Check the status of an asset scan

  • get_asset_issues: Get all quality issues for an asset

  • get_asset_content: Get the HTML content for an asset

  • get_asset_errors: Get asset errors for a specific checkpoint with highlighted content

  • get_asset_pagehighlight: (Beta) Get asset content with all page highlightable issues highlighted

  • update_asset: Update the content of an existing asset

  • delete_asset: Delete a specific asset from DQM storage

Quality Checking

  • run_quality_check: Run a quality check on a URL or HTML content

    • Accepts: websiteId, url (optional), html (optional), metadata (optional)

    • Creates asset, returns issues immediately

    • Rate limited to prevent overload

Spellcheck

  • spellcheck_asset: Run spellcheck on an asset

    • Accepts: assetId, websiteId, url, html, language (optional)

    • Can use existing asset or create new one automatically

Configuration

All configuration via environment variables. See .env.example for all options.

Required

  • DQM_API_KEY: Your Crownpeak DQM API key

Optional

  • DQM_API_BASE_URL: Override base URL (default: https://api.crownpeak.net/dqm-cms/v1)

  • PORT: HTTP server port (default: 3000)

  • ENABLE_DESTRUCTIVE_TOOLS: Enable delete operations (default: false)

  • DQM_REQUEST_TIMEOUT: Request timeout in ms (default: 30000)

  • MAX_CONCURRENT_QUALITY_CHECKS: Concurrent quality check limit (default: 3)

Testing Configuration

  • DQM_WEBSITE_ID: Website ID for integration tests

  • DQM_TEST_URL: URL to test against (default: https://www.crownpeak.com)

Development

Run in Development Mode

npm run dev

Run Tests

# Run unit tests npm test # Watch mode npm run test:watch # Run integration tests (requires API key and website ID in .env) npm run test:integration

The integration test suite validates all 15 API endpoints against the live DQM API with 100% test coverage.

Linting

npm run lint

Type Checking

npm run typecheck

Architecture

src/ ├── types.ts # TypeScript type definitions ├── config.ts # Configuration management ├── dqmClient.ts # DQM API client ├── tools.ts # MCP tool definitions ├── server.ts # MCP server (stdio transport) ├── http.ts # HTTP server entry point ├── index.ts # Stdio entry point └── *.test.ts # Test files tests/ └── integration/ └── api-test.ts # Integration tests for all 15 endpoints

API Client Features

  • Automatic dual authentication (x-api-key header + query parameter)

  • Request timeouts

  • Error handling with structured errors

  • Rate limiting for quality checks

  • Issue normalization

  • Proper handling of text/HTML and JSON responses

  • Support for form-encoded POST/PUT requests

Security

  • API keys loaded from environment (never hardcoded)

  • Non-root Docker user

  • Read-only operations by default

  • Request timeouts prevent hanging

  • Rate limiting prevents abuse

  • Comprehensive error handling (no secret leakage)

Troubleshooting

"DQM_API_KEY environment variable is required"

Set your API key in .env or pass it directly:

DQM_API_KEY=your_key npm start

Connection timeouts

Increase timeout:

DQM_REQUEST_TIMEOUT=60000 npm run start:http

Docker health check fails

Ensure the container is running and port 3000 is accessible:

docker logs crownpeak-dqm-mcp curl http://localhost:3000/healthz

Integration tests fail

Make sure you have set up the test configuration in .env:

DQM_API_KEY=your_api_key_here DQM_WEBSITE_ID=your_website_id_here DQM_TEST_URL=https://www.crownpeak.com

This is an example solution subject to the MIT license.

Disclaimer

This document is provided for information purposes only. Paul Taylor may change the contents hereof without notice. This document is not warranted to be error-free, nor subject to any other warranties or conditions, whether expressed orally or implied in law, including implied warranties and conditions of merchantability or fitness for a particular purpose. Paul Taylor specifically disclaims any liability with respect to this document and no contractual obligations are formed either directly or indirectly by this document. The technologies, functionality, services, and processes described herein are subject to change without notice.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ptylr/crownpeak-dqm-node-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server