An MCP (Model Context Protocol) server that wraps the Ex Libris Primo Search API, enabling LLMs to search library catalogs.
- Node.js 22+
- npm
- Docker (for containerized deployment)
- Kubernetes cluster (for K8s deployment)
- Ex Libris Primo API key
npm install
npm run build
PRIMO_API_KEY=your-key PRIMO_VID=your-vid PRIMO_TAB=your-tab PRIMO_SCOPE=your-scope npm startThe server starts on port 3000 (configurable via PORT).
GET /healthz— liveness probeGET /readyz— readiness probe
POST /mcp— stateless Streamable HTTP transport (one request per MCP session)
docker build -t primomcp .
docker run -e PRIMO_API_KEY=your-key \
-e PRIMO_VID=your-vid \
-e PRIMO_TAB=your-tab \
-e PRIMO_SCOPE=your-scope \
-p 3000:3000 primomcpThe manifests in k8s/ are managed with kustomize and
deploy to the vtlib namespace (namespace, image, and ingress host are set in
the committed manifests). Per-institution config and all secrets are kept out of
version control: they live in .env and are rendered into gitignored kustomize
generator inputs (k8s/config.env, k8s/secret.env, k8s/dockerconfigjson).
- Copy
.env.sampleto.envand fill in your values:
cp .env.sample .env
# PRIMO_API_KEY, PRIMO_VID/TAB/SCOPE, CONTAINER_REGISTRY, REGISTRY_* (deploy token)- Build and push the Docker image:
./scripts/build.sh # builds and pushes $CONTAINER_REGISTRY/primomcp:latest- Render the gitignored kustomize inputs from
.env:
./scripts/gen-kustomize-inputs.sh- Deploy with kustomize:
kubectl --kubeconfig endeavour.yaml apply -k k8sSteps 3–4 are also wrapped by ./scripts/deploy.sh, which renders the inputs,
applies k8s/ against endeavour.yaml, and waits for the rollout. Re-run
gen-kustomize-inputs.sh whenever .env changes; otherwise kubectl apply -k k8s
is self-contained.
Search a library catalog via the Primo Search API.
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | One of query or advancedQuery required |
Simple keyword search |
advancedQuery |
string | One of query or advancedQuery required |
Raw Primo q format (e.g., title,contains,machine learning) |
limit |
integer | No | Max results, 1-50 (default 10) |
offset |
integer | No | Pagination offset, 0-5000 (default 0) |
sort |
string | No | Sort order: rank, title, author, date, date_d, date_a |
qInclude |
string | No | Include facet filter |
qExclude |
string | No | Exclude facet filter |
lang |
string | No | Language code |
Simple search:
{ "query": "machine learning" }Advanced search:
{ "advancedQuery": "title,contains,machine learning,AND;sub,contains,neural networks", "limit": 5 }| Variable | Required | Default | Description |
|---|---|---|---|
PRIMO_API_KEY |
Yes | — | Ex Libris API key |
PRIMO_BASE_URL |
No | https://api-na.hosted.exlibrisgroup.com |
Primo API base URL |
PRIMO_VID |
Yes | — | View ID |
PRIMO_TAB |
Yes | — | Tab name |
PRIMO_SCOPE |
Yes | — | Scope name |
PRIMO_INST |
No | — | Institution code (on-premises only) |
PORT |
No | 3000 |
Server listen port |