mcp server
scalepad-mcp
MCP server for ScalePad — full product coverage (Lifecycle Manager, Backup Radar, ControlMap, Quoter), MCP SDK v2 dual-era
Set up
Runs on your computer. Pick your agent and operating system.
Before you start
- Docker Desktop
{
"mcpServers": {
"scalepad-mcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"SCALEPAD_API_KEY",
"-e",
"SCALEPAD_REGION",
"-e",
"QUOTER_CLIENT_ID",
"-e",
"QUOTER_CLIENT_SECRET",
"-e",
"MCP_TRANSPORT",
"-e",
"AUTH_MODE",
"-e",
"LOG_LEVEL",
"ghcr.io/wyre-technology/scalepad-mcp:v1.0.5"
],
"env": {
"SCALEPAD_API_KEY": "<your SCALEPAD_API_KEY>"
}
}
}
}same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12
Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs
README
synced Oct 14, 2026scalepad-mcp
MCP server for the ScalePad platform — Core, Lifecycle Manager, ControlMap, Backup Radar, and Quoter — built natively on the MCP SDK v2 (2026-07-28 spec) with dual-era serving: the same endpoint answers both legacy 2025-era initialize-handshake clients and modern envelope clients.
Architecture
Flat tool surface: every tool is exposed upfront in tools/list for universal client compatibility. Navigation tools are discovery aids, not gates.
| Tool | Purpose |
|---|---|
scalepad_navigate | Describe a product domain's tools (core, lifecycle-manager, controlmap, backup-radar, quoter) — a help/discovery aid, not a prerequisite |
scalepad_status | Show credential status and available domains |
Product domains
| Domain | Tool prefix | Coverage |
|---|---|---|
core | scalepad_core_ | Unified platform data (read-only, US-only): clients, contacts, members, sites, opportunities, hardware/SaaS assets, product catalog, service contracts, tickets, integrations |
lifecycle-manager | scalepad_lm_ | Engagement/roadmap workflows: initiatives, goals, meetings, action items, assessments, deliverables, budgets, contracts, workspace |
controlmap | scalepad_cm_ | Compliance per client: risks, controls, evidence, policies, frameworks, assessments, action items (regions: us, eu, ca, au) |
backup-radar | scalepad_br_ | Read-only backup health and backup device inventory (regions: us, eu) |
quoter | scalepad_quoter_ | Quotes, catalog, contacts, suppliers, and standalone-OAuth helpers (defaults to the ScalePad-hosted Quoter API) |
All tools are callable at any time; scalepad_navigate simply summarizes a domain's tools.
Credentials
One ScalePad API key (generated in the ScalePad app by an Administrator) covers every product; endpoints for products without an active subscription return 402.
Copy .env.example and set the variables below. Leave CONDUIT_S2S_SECRET empty in that file.
Environment variables (AUTH_MODE=env, default for stdio/local)
| Variable | Required | Notes |
|---|---|---|
SCALEPAD_API_KEY | For stdio and AUTH_MODE=env | Forwarded to api.scalepad.com as x-api-key |
SCALEPAD_REGION | no | us (default), eu, ca, or au — selects the regional base URL for ControlMap (us/eu/ca/au) and Backup Radar (us/eu); Core and Lifecycle Manager are US-only |
QUOTER_CLIENT_ID | no | Only for the standalone api.quoter.com OAuth path (Quoter Account > API Keys, Account Owner only) |
QUOTER_CLIENT_SECRET | no | Paired with QUOTER_CLIENT_ID |
MCP_TRANSPORT | no | stdio (default) or http |
AUTH_MODE | no | gateway (Docker image and Compose default) or env. Gateway mode requires X-ScalePad-Api-Key on each /mcp request and never falls back to SCALEPAD_*. env uses those variables only after S2S auth succeeds. |
CONDUIT_S2S_SECRET | Yes for HTTP | Service-to-service secret. The HTTP server logs an error and exits non-zero when this is empty or a known placeholder (changeme, your-s2s-secret, and similar copied example values). Compose will not start without it. Never commit a real value. The value is never logged. |
MCP_ALLOW_INSECURE_DEV | no | Set to exactly 1 only for local development to start HTTP without CONDUIT_S2S_SECRET. The process logs a warning and does not enforce X-Gateway-S2S. The listener is forced to 127.0.0.1 even if MCP_HTTP_HOST is a wider address such as 0.0.0.0. A known placeholder secret is still refused. |
MCP_HTTP_HOST | no | Bind address when MCP_TRANSPORT=http and CONDUIT_S2S_SECRET is set. When unset, the server binds 127.0.0.1. The container image sets 0.0.0.0. |
MCP_HTTP_PORT | no | HTTP port. Defaults to 8080. |
/health and /healthz stay unauthenticated and do not read credentials. The stdio transport does not use CONDUIT_S2S_SECRET.
Gateway headers (AUTH_MODE=gateway, hosted deployment)
| Header | Required |
|---|---|
X-Gateway-S2S | yes, when CONDUIT_S2S_SECRET is set |
X-ScalePad-Api-Key | yes |
X-ScalePad-Region | no |
X-Quoter-Client-Id | no |
X-Quoter-Client-Secret | no |
In gateway mode credentials are bound per request from these headers. A /mcp request without X-ScalePad-Api-Key is rejected with a 401 JSON-RPC error before any MCP handling and never falls through to env credentials. /health stays unauthenticated.
X-Gateway-S2S signing
With MCP_TRANSPORT=http and CONDUIT_S2S_SECRET set, every /mcp request must include X-Gateway-S2S. A missing or invalid header returns 401 before vendor credentials are read.
The header value is t=<unix seconds>,v1=<hex>. v1 is HMAC-SHA256 (64 lowercase hex characters) of the ASCII string t=<unix seconds>, keyed with CONDUIT_S2S_SECRET. Timestamps more than 300 seconds from the server clock are rejected.
import { createHmac } from "node:crypto";
const t = Math.floor(Date.now() / 1000);
const v1 = createHmac("sha256", process.env.CONDUIT_S2S_SECRET).update(`t=${t}`).digest("hex");
const xGatewayS2s = `t=${t},v1=${v1}`;
Transports
- stdio (default):
node dist/index.js— for Claude Desktop / CLI. Does not useCONDUIT_S2S_SECRET. - HTTP:
MCP_TRANSPORT=http node dist/index.js— serves/mcp(dual-era,legacy: 'stateless') plus/healthand/healthz. Refuses to start untilCONDUIT_S2S_SECRETis a real secret.MCP_HTTP_PORTdefaults to8080. With a secret set,MCP_HTTP_HOSTis honored and defaults to127.0.0.1when unset. Without a secret,MCP_ALLOW_INSECURE_DEV=1is the only way to start, and the listener is127.0.0.1only.
Development
export NODE_AUTH_TOKEN=$(gh auth token) # GitHub Packages read access
npm ci
npm run build # tsup (transpile-only; domains stay lazily importable)
npm test # vitest (HTTP layer: health, 401 gate, dual-era tools/list, fail-closed S2S)
npm run smoke # dual-era smoke against dist/index.js (loopback, insecure-dev bypass)
npm run typecheck
Domain handlers live in src/domains/<slug>.ts, each exporting export const handler: DomainHandler (see src/utils/types.ts), and are lazily loaded via src/domains/index.ts.
Local HTTP without a secret:
MCP_TRANSPORT=http MCP_ALLOW_INSECURE_DEV=1 npm start
Docker
The image listens on 0.0.0.0 inside the container (MCP_HTTP_HOST) and defaults to AUTH_MODE=gateway. That bind is safe only because startup refuses to run without a real CONDUIT_S2S_SECRET. Publish the port on loopback and pass the S2S secret. In gateway mode, ScalePad credentials arrive on each request as headers; they are not read from the environment.
docker build --build-arg NODE_AUTH_TOKEN=$(gh auth token) -t scalepad-mcp .
docker run \
-e CONDUIT_S2S_SECRET="$CONDUIT_S2S_SECRET" \
-p 127.0.0.1:8080:8080 \
scalepad-mcp
Compose refuses to start when CONDUIT_S2S_SECRET is unset. The gateway service does not set SCALEPAD_API_KEY, QUOTER_CLIENT_ID, or QUOTER_CLIENT_SECRET, and it does not use env_file, so a project .env cannot inject static vendor credentials into the container. Compose still interpolates CONDUIT_S2S_SECRET from that file. It publishes 127.0.0.1:8080:8080:
CONDUIT_S2S_SECRET="$CONDUIT_S2S_SECRET" docker compose up
Single-tenant HTTP (AUTH_MODE=env) still requires the S2S secret, then uses SCALEPAD_API_KEY:
docker run \
-e CONDUIT_S2S_SECRET="$CONDUIT_S2S_SECRET" \
-e AUTH_MODE=env \
-e SCALEPAD_API_KEY=your-value \
-e SCALEPAD_REGION=us \
-p 127.0.0.1:8080:8080 \
scalepad-mcp
Local HTTP without a secret is development-only. It binds 127.0.0.1 only (a non-loopback MCP_HTTP_HOST, including 0.0.0.0, is overridden) and logs a warning:
MCP_TRANSPORT=http MCP_ALLOW_INSECURE_DEV=1 npm start
The image defaults to AUTH_MODE=gateway for hosted deployment behind the WYRE MCP gateway.
License
Apache-2.0 — see LICENSE.