@coret/openarchieven-mcp-server
v1.0.0
Published
MCP server for the Open Archives genealogical search engine.
Readme
Open Archieven MCP Server v1.0
Production-grade hybrid MCP + HTTP + SSE server generated from the Open Archieven OpenAPI specification.
OpenAPI source used to generate tools:
../api/openapi.yaml (local)
https://api.openarchieven.nl/openapi.yaml (remote)Overview
A schema-aware server that automatically converts the OpenAPI specification into callable tools and exposes them through multiple transports:
- MCP Remote (JSON-RPC over StreamableHTTP)
- HTTP JSON API
- SSE streaming with auto-pagination
- Chunked HTTP streaming with auto-pagination
- Redis caching (optional)
- Health checks
Core Features
OpenAPI Auto-Generation
Every API operation becomes a tool automatically via generate.ts.
All 17 operations:
| Tool Name | Description |
| ---------------------- | -------------------------------------------- |
| search_records | Search genealogical records |
| show_record | Show a single genealogical record |
| match_record | Match a person to birth and death records |
| get_births_years_ago | List births from N years ago |
| get_births | Find birth records |
| get_deaths | Find death records |
| get_marriages | Find marriage records |
| get_archives | List all archives with statistics |
| get_record_stats | Record count per archive |
| get_source_type_stats | Record count per source type |
| get_event_type_stats | Record count per event type |
| get_comment_stats | Comment count statistics |
| get_family_name_stats | Family name frequency |
| get_first_name_stats | First name frequency |
| get_profession_stats | Profession frequency |
| get_historical_weather | Historical weather from KNMI |
| get_census_data | Dutch census data 1795–1899 |
Note: The
callback(JSONP) parameter present in the upstream API is excluded from all tools — it is irrelevant in an MCP/JSON-RPC context.
Schema-Perfect Validation
Uses actual OpenAPI parameter schemas. Validates:
- required parameters
- integer fields
- number fields
- enum values
- minimum / maximum constraints
Tool Aliases
Friendly aliases are included:
| Alias | Real Tool |
| -------------- | --------------- |
| search_person | search_records |
| get_record | show_record |
| list_archives | get_archives |
Multiple Interfaces
MCP Remote (StreamableHTTP)
POST / ← canonical public endpoint (mcp.openarchieven.nl)
POST /mcp ← local / legacy aliasStateless JSON-RPC transport — a new MCP server instance is created per request.
Required header: All MCP
POSTrequests must includeAccept: application/json, text/event-stream. Omitting it returns a-32000 Not Acceptableerror. MCP clients (Claude Desktop, etc.) send this automatically.
HTTP JSON
GET /tools
POST /tools/:nameSSE Streaming (auto-paginating)
GET /events/:nameChunked HTTP Streaming (auto-paginating)
POST /stream/:namePagination
Streaming endpoints (/events/:name, /stream/:name) automatically paginate through results for endpoints that support a start offset:
- Increments
startbynumber_showper page - Stops when results are exhausted or after 20 pages (safety cap)
- SSE sends a
: heartbeatcomment every 10 seconds to keep connections alive
Redis Cache
Optional Redis support.
If Redis is running:
- responses are cached for 1 hour (configurable via
CACHE_TTL)
If Redis is unavailable:
- server still runs normally (degraded mode)
Rate Limiting
The upstream API enforces 4 requests per second per IP. The server queues all upstream calls through a token-bucket rate limiter (configurable via RATE_LIMIT_RPS).
Health Checks
GET /healthProject Files
generate.ts
server.ts
tsconfig.json
package.json
.env.example
generated/
tools.json
spec.jsonRequirements
- Node.js 18+
- npm
- optional Redis server
Configuration
Copy .env.example to .env and adjust:
cp .env.example .env| Variable | Default | Description |
|-----------------|--------------------------------------|-------------------------------|
| PORT | 3001 | HTTP port |
| OPENAPI_PATH | ../api/openapi.yaml | Path or URL to OpenAPI spec |
| UPSTREAM_BASE | https://api.openarchieven.nl/1.1 | Upstream API base URL |
| RATE_LIMIT_RPS| 4 | Upstream requests per second |
| REDIS_URL | redis://localhost:6379/5 | Redis connection URL (db 5) |
| CACHE_TTL | 3600 | Cache TTL in seconds |
| LOG_LEVEL | info | trace debug info warn error fatal |
| NODE_ENV | (unset) | Set to production for JSON logs (default: pretty-printed) |
Install
npm installGenerate Tools from OpenAPI YAML
Run from local spec:
npx tsx generate.tsOr from remote URL:
npx tsx generate.ts https://api.openarchieven.nl/openapi.yamlExpected result:
Generated 17 tools
Output: generated/tools.json, generated/spec.jsonCreates:
generated/tools.json
generated/spec.jsonStart Server
npx tsx server.tsExpected startup (development — pretty-printed):
[12:00:00] INFO: Open Archieven MCP server started
port: 3001
tools: 17
aliases: 3
upstream: "https://api.openarchieven.nl/1.1"
rateLimit: "4 req/s"
redis: "redis://localhost:6379/5"
env: "development"In production (NODE_ENV=production) each log line is a single JSON object.
Server binds to:
http://0.0.0.0:3001Test All Features
1. Health Check
curl http://localhost:3001/healthExpected:
{
"ok": true,
"tools": 17,
"aliases": 3,
"redis": false,
"uptime": 1.23
}2. List Tools
curl http://localhost:3001/toolsExpected:
[
"search_records",
"show_record",
"match_record",
"get_births_years_ago",
"get_births",
"get_deaths",
"get_marriages",
"get_archives",
"get_record_stats",
"get_source_type_stats",
"get_event_type_stats",
"get_comment_stats",
"get_family_name_stats",
"get_first_name_stats",
"get_profession_stats",
"get_historical_weather",
"get_census_data",
"search_person",
"get_record",
"list_archives"
]3. Normal Tool Call (via alias)
curl -X POST http://localhost:3001/tools/search_person \
-H "Content-Type: application/json" \
-d '{"name":"Jansen"}'4. Canonical Tool Call
curl -X POST http://localhost:3001/tools/search_records \
-H "Content-Type: application/json" \
-d '{"name":"Jansen"}'5. Show a Single Record
curl -X POST http://localhost:3001/tools/show_record \
-H "Content-Type: application/json" \
-d '{"archive":"hua","identifier":"E13B9821-C0B0-4AED-B20B-8DE627ED99BD"}'6. SSE Streaming
curl -N "http://localhost:3001/events/search_records?name=Coret"Expected stream:
event: page
data: {...}
event: page
data: {...}
event: done
data: {}7. Heartbeat Test
Leave SSE open for 15+ seconds — expect periodic keep-alive lines:
: heartbeat8. Chunked HTTP Streaming
curl -N -X POST http://localhost:3001/stream/search_records \
-H "Content-Type: application/json" \
-d '{"name":"Jansen"}'Expected (newline-delimited JSON):
{"query":{...},"response":{"number_found":...,"docs":[...]}}
{"query":{...},"response":{"number_found":...,"docs":[...]}}9. MCP Initialize
curl -X POST http://localhost:3001/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": { "name": "test", "version": "1.0" }
}
}'10. MCP List Tools
curl -X POST http://localhost:3001/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}'11. MCP Call Tool
curl -X POST http://localhost:3001/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "search_person",
"arguments": { "name": "Jansen" }
}
}'Redis Testing
Start Redis
redis-serverRestart the MCP server. Expected in /health:
{ "redis": true }Without Redis
Stop Redis and restart. Expected:
{ "redis": false }Common Commands
Regenerate after API changes
npx tsx generate.tsRestart server
npx tsx server.tsTroubleshooting
Generated files missing
npx tsx generate.tsPort already in use
Linux / macOS:
lsof -i :3001
kill -9 <PID>Windows:
netstat -ano | findstr :3001
taskkill /PID <PID> /FRedis not connecting
Server runs normally without Redis. Check REDIS_URL in .env.
Rate limit errors (429)
The upstream API allows 4 req/s per IP. The built-in rate limiter queues requests automatically. If you are running multiple server instances, reduce RATE_LIMIT_RPS or use a shared queue.
Recommended Production Upgrades
- HTTPS reverse proxy (nginx / caddy)
- PM2 or systemd process manager
- Structured JSON logging (pino / winston)
- Request tracing (OpenTelemetry)
- Auth middleware if server is public-facing
- Shared Redis for multi-instance deployments
Version
v1.0Schema-perfect OpenAPI-generated MCP server for Open Archieven.
