Crescender MCP Server
Model Context Protocol server for Crescender's public read API. Connects AI clients (Claude Desktop, Cursor, custom agents) to a school's assets, loans, members, and asset-comms threads — all read-only, scope-token-authenticated, and bound to a single school per token.
Status: 0.0.x — pre-publish. This package has not yet been published to npm or pushed to GHCR. The publish pipelines exist but are gated to manual triggers; the first release ships when the source has been pressure-tested locally. For now, run from a clone or a
pnpm link(see Local development below).
What it gives an AI
Six read-only tools, each backed by an /api/v1/* endpoint:
| MCP tool | Returns |
|---|---|
list_schools | The single school the token is bound to (single-item array) |
get_asset | Full asset detail by id — model, serial, location, role, current loan |
search_assets | Up to 50 assets matching q / item_class / category / status |
get_loans_for_asset | Loan history for one asset (current + past) |
list_members | Member directory — id, role, status, external_id (no PII) |
list_asset_threads | Asset-comms threads with status filter (read-only — vendor-token issuance is NOT exposed via MCP) |
Reads only. No update_* / create_* tools in v1.
Configuration
Two environment variables, one of them required:
| Var | Default | Notes |
|---|---|---|
CRESCENDER_API_TOKEN | — | Required. Issue from https://app.crescender.com.au/school/<id>/settings/integrations (the "Integrations" tile under your school's Settings). Format crsc_<random>. |
CRESCENDER_API_URL | https://app.crescender.com.au | Override only if you're pointing at a non-production deployment. |
CRESCENDER_MCP_LOG_LEVEL | info | One of debug / info / warn / error. Logs go to stderr (stdout is reserved for the MCP protocol). |
CRESCENDER_MCP_HEALTH | 0 | Set to 1 in container deployments to enable the GET /health HTTP endpoint on PORT (default 3030). |
CRESCENDER_API_TIMEOUT_MS | 15000 | Per-request upstream timeout. |
Connecting Claude Desktop (once published)
Once the first version is on npm:
// ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)
// %APPDATA%\Claude\claude_desktop_config.json (Windows)
{
"mcpServers": {
"crescender": {
"command": "npx",
"args": ["-y", "@crescender/mcp-server"],
"env": {
"CRESCENDER_API_TOKEN": "crsc_..."
}
}
}
}
Then restart Claude Desktop. The six tools should appear in the MCP picker.
Connecting Cursor (once published)
Cursor reads MCP config from .cursor/mcp.json in your workspace, or globally from settings. The shape is the same as Claude Desktop's mcpServers block.
Local development
# Install
git clone https://github.com/lincalinca/crescender-mcp-server.git
cd crescender-mcp-server
pnpm install
# Build
pnpm build
# Smoke test (talks to stdin/stdout — Claude Desktop / Cursor will spawn it
# the same way)
CRESCENDER_API_TOKEN=crsc_... node dist/index.js
To wire your local clone into Claude Desktop without publishing:
{
"mcpServers": {
"crescender-local": {
"command": "node",
"args": ["/absolute/path/to/crescender-mcp-server/dist/index.js"],
"env": {
"CRESCENDER_API_TOKEN": "crsc_..."
}
}
}
}
Container
# Build (the published image is built by .github/workflows/publish-image.yml)
docker build -t crescender-mcp-server:dev .
# Run with the in-container /health endpoint enabled
docker run --rm -i \
-e CRESCENDER_API_TOKEN=crsc_... \
-e CRESCENDER_MCP_HEALTH=1 \
-p 3030:3030 \
crescender-mcp-server:dev
Once published, the image will be available at ghcr.io/lincalinca/crescender-mcp-server.
Statelessness contract
- No in-memory token cache: validation hits the upstream API on every call (revocation is immediate).
- No filesystem state: stdout/stderr only.
- Config is env-driven, parsed once at boot, frozen.
/health(when enabled) returns{ ok, api_reachable, version }and probes the upstream/api/v1/healthto verify reachability — not just "this process is alive."- Graceful shutdown: SIGTERM / SIGINT trigger a 30-second drain, then force-exit.
This is what makes the container k8s-ready without any k8s-specific code. When the orchestration decision is eventually made (ASK / AKS / GKE / Fly / Railway / etc.), nothing changes here.
License
MIT — see LICENSE.
Related
@crescender/crescender-core— the platform itself, which serves the/api/v1endpoints this MCP wraps.- OpenAPI spec:
https://app.crescender.com.au/api/v1/openapi.json