{"_id":"@coret/openarchieven-mcp-server","_rev":"2-d144298b94949bb8815189fab2070bef","name":"@coret/openarchieven-mcp-server","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@coret/openarchieven-mcp-server","version":"1.0.0","_id":"@coret/openarchieven-mcp-server@1.0.0","maintainers":[{"name":"coret","email":"bob@coret.org"}],"dist":{"shasum":"b00e0df5d1e58282e3d17372b0fda7847b6bcefd","tarball":"https://registry.npmjs.org/@coret/openarchieven-mcp-server/-/openarchieven-mcp-server-1.0.0.tgz","fileCount":6,"integrity":"sha512-yXoVazxKescCB7SIxPT5PSV+tCJO3UFyr3Mb33ODMFiyJGKiG1pZ/wNA3UW77D2baTEXWyhkmOhnaqYZTIePfw==","signatures":[{"sig":"MEQCIBEUHrsU6lYH21/LEk7Ssn0MNOlK628wboewAfW21WkgAiAZyNuXuXFDxsesutzoeAbgIendx++T7mwkVjzsA3VKYA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":34529},"type":"module","gitHead":"d6b48e66cefed44c6c2ff76f50857ef0f4c6fc36","mcpName":"io.github.coret/openarchieven-mcp-server","scripts":{"build":"tsc","start":"tsx server.ts","generate":"tsx generate.ts"},"_npmUser":{"name":"coret","email":"bob@coret.org"},"_npmVersion":"10.9.2","description":"MCP server for the Open Archives genealogical search engine.","directories":{},"_nodeVersion":"22.13.1","dependencies":{"zod":"^3.24.2","pino":"^9.6.0","yaml":"^2.7.0","axios":"^1.7.9","express":"^4.21.2","ioredis":"^5.4.2","pino-pretty":"^13.0.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","typescript":"^5.7.3","@types/node":"^22.0.0","@types/express":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/openarchieven-mcp-server_1.0.0_1777152237313_0.737300905193476","host":"s3://npm-registry-packages-npm-production"},"deprecated":"No longer distributed via npm — use the hosted MCP server at https://mcp.openarchieven.nl/"}},"time":{"created":"2026-04-25T21:23:57.173Z","modified":"2026-07-31T21:13:08.339Z","1.0.0":"2026-04-25T21:23:57.479Z"},"description":"MCP server for the Open Archives genealogical search engine.","maintainers":[{"name":"coret","email":"bob@coret.org"}],"readme":"# Open Archieven MCP Server v1.0\n\nProduction-grade hybrid MCP + HTTP + SSE server generated from the Open Archieven OpenAPI specification.\n\nOpenAPI source used to generate tools:\n\n```\n../api/openapi.yaml   (local)\nhttps://api.openarchieven.nl/openapi.yaml   (remote)\n```\n\n---\n\n# Overview\n\nA schema-aware server that automatically converts the OpenAPI specification into callable tools and exposes them through multiple transports:\n\n* MCP Remote (JSON-RPC over StreamableHTTP)\n* HTTP JSON API\n* SSE streaming with auto-pagination\n* Chunked HTTP streaming with auto-pagination\n* Redis caching (optional)\n* Health checks\n\n---\n\n# Core Features\n\n## OpenAPI Auto-Generation\n\nEvery API operation becomes a tool automatically via `generate.ts`.\n\nAll 17 operations:\n\n| Tool Name | Description |\n| ---------------------- | -------------------------------------------- |\n| `search_records` | Search genealogical records |\n| `show_record` | Show a single genealogical record |\n| `match_record` | Match a person to birth and death records |\n| `get_births_years_ago` | List births from N years ago |\n| `get_births` | Find birth records |\n| `get_deaths` | Find death records |\n| `get_marriages` | Find marriage records |\n| `get_archives` | List all archives with statistics |\n| `get_record_stats` | Record count per archive |\n| `get_source_type_stats` | Record count per source type |\n| `get_event_type_stats` | Record count per event type |\n| `get_comment_stats` | Comment count statistics |\n| `get_family_name_stats` | Family name frequency |\n| `get_first_name_stats` | First name frequency |\n| `get_profession_stats` | Profession frequency |\n| `get_historical_weather` | Historical weather from KNMI |\n| `get_census_data` | Dutch census data 1795–1899 |\n\n> **Note:** The `callback` (JSONP) parameter present in the upstream API is excluded from all tools — it is irrelevant in an MCP/JSON-RPC context.\n\n---\n\n## Schema-Perfect Validation\n\nUses actual OpenAPI parameter schemas. Validates:\n\n* required parameters\n* integer fields\n* number fields\n* enum values\n* minimum / maximum constraints\n\n---\n\n## Tool Aliases\n\nFriendly aliases are included:\n\n| Alias | Real Tool |\n| -------------- | --------------- |\n| `search_person` | `search_records` |\n| `get_record` | `show_record` |\n| `list_archives` | `get_archives` |\n\n---\n\n## Multiple Interfaces\n\n### MCP Remote (StreamableHTTP)\n\n```text\nPOST /       ← canonical public endpoint (mcp.openarchieven.nl)\nPOST /mcp    ← local / legacy alias\n```\n\nStateless JSON-RPC transport — a new MCP server instance is created per request.\n\n> **Required header:** All MCP `POST` requests must include `Accept: application/json, text/event-stream`. Omitting it returns a `-32000 Not Acceptable` error. MCP clients (Claude Desktop, etc.) send this automatically.\n\n### HTTP JSON\n\n```text\nGET  /tools\nPOST /tools/:name\n```\n\n### SSE Streaming (auto-paginating)\n\n```text\nGET /events/:name\n```\n\n### Chunked HTTP Streaming (auto-paginating)\n\n```text\nPOST /stream/:name\n```\n\n---\n\n## Pagination\n\nStreaming endpoints (`/events/:name`, `/stream/:name`) automatically paginate through results for endpoints that support a `start` offset:\n\n* Increments `start` by `number_show` per page\n* Stops when results are exhausted or after 20 pages (safety cap)\n* SSE sends a `: heartbeat` comment every 10 seconds to keep connections alive\n\n---\n\n## Redis Cache\n\nOptional Redis support.\n\nIf Redis is running:\n\n* responses are cached for 1 hour (configurable via `CACHE_TTL`)\n\nIf Redis is unavailable:\n\n* server still runs normally (degraded mode)\n\n---\n\n## Rate Limiting\n\nThe 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`).\n\n---\n\n## Health Checks\n\n```text\nGET /health\n```\n\n---\n\n# Project Files\n\n```text\ngenerate.ts\nserver.ts\ntsconfig.json\npackage.json\n.env.example\ngenerated/\n  tools.json\n  spec.json\n```\n\n---\n\n# Requirements\n\n* Node.js 18+\n* npm\n* optional Redis server\n\n---\n\n# Configuration\n\nCopy `.env.example` to `.env` and adjust:\n\n```bash\ncp .env.example .env\n```\n\n| Variable | Default | Description |\n|-----------------|--------------------------------------|-------------------------------|\n| `PORT` | `3001` | HTTP port |\n| `OPENAPI_PATH` | `../api/openapi.yaml` | Path or URL to OpenAPI spec |\n| `UPSTREAM_BASE` | `https://api.openarchieven.nl/1.1` | Upstream API base URL |\n| `RATE_LIMIT_RPS`| `4` | Upstream requests per second |\n| `REDIS_URL` | `redis://localhost:6379/5` | Redis connection URL (db 5) |\n| `CACHE_TTL` | `3600` | Cache TTL in seconds |\n| `LOG_LEVEL` | `info` | `trace` `debug` `info` `warn` `error` `fatal` |\n| `NODE_ENV` | _(unset)_ | Set to `production` for JSON logs (default: pretty-printed) |\n\n---\n\n# Install\n\n```bash\nnpm install\n```\n\n---\n\n# Generate Tools from OpenAPI YAML\n\nRun from local spec:\n\n```bash\nnpx tsx generate.ts\n```\n\nOr from remote URL:\n\n```bash\nnpx tsx generate.ts https://api.openarchieven.nl/openapi.yaml\n```\n\nExpected result:\n\n```text\nGenerated 17 tools\nOutput: generated/tools.json, generated/spec.json\n```\n\nCreates:\n\n```text\ngenerated/tools.json\ngenerated/spec.json\n```\n\n---\n\n# Start Server\n\n```bash\nnpx tsx server.ts\n```\n\nExpected startup (development — pretty-printed):\n\n```text\n[12:00:00] INFO: Open Archieven MCP server started\n    port: 3001\n    tools: 17\n    aliases: 3\n    upstream: \"https://api.openarchieven.nl/1.1\"\n    rateLimit: \"4 req/s\"\n    redis: \"redis://localhost:6379/5\"\n    env: \"development\"\n```\n\nIn production (`NODE_ENV=production`) each log line is a single JSON object.\n\nServer binds to:\n\n```text\nhttp://0.0.0.0:3001\n```\n\n---\n\n# Test All Features\n\n---\n\n# 1. Health Check\n\n```bash\ncurl http://localhost:3001/health\n```\n\nExpected:\n\n```json\n{\n  \"ok\": true,\n  \"tools\": 17,\n  \"aliases\": 3,\n  \"redis\": false,\n  \"uptime\": 1.23\n}\n```\n\n---\n\n# 2. List Tools\n\n```bash\ncurl http://localhost:3001/tools\n```\n\nExpected:\n\n```json\n[\n  \"search_records\",\n  \"show_record\",\n  \"match_record\",\n  \"get_births_years_ago\",\n  \"get_births\",\n  \"get_deaths\",\n  \"get_marriages\",\n  \"get_archives\",\n  \"get_record_stats\",\n  \"get_source_type_stats\",\n  \"get_event_type_stats\",\n  \"get_comment_stats\",\n  \"get_family_name_stats\",\n  \"get_first_name_stats\",\n  \"get_profession_stats\",\n  \"get_historical_weather\",\n  \"get_census_data\",\n  \"search_person\",\n  \"get_record\",\n  \"list_archives\"\n]\n```\n\n---\n\n# 3. Normal Tool Call (via alias)\n\n```bash\ncurl -X POST http://localhost:3001/tools/search_person \\\n-H \"Content-Type: application/json\" \\\n-d '{\"name\":\"Jansen\"}'\n```\n\n---\n\n# 4. Canonical Tool Call\n\n```bash\ncurl -X POST http://localhost:3001/tools/search_records \\\n-H \"Content-Type: application/json\" \\\n-d '{\"name\":\"Jansen\"}'\n```\n\n---\n\n# 5. Show a Single Record\n\n```bash\ncurl -X POST http://localhost:3001/tools/show_record \\\n-H \"Content-Type: application/json\" \\\n-d '{\"archive\":\"hua\",\"identifier\":\"E13B9821-C0B0-4AED-B20B-8DE627ED99BD\"}'\n```\n\n---\n\n# 6. SSE Streaming\n\n```bash\ncurl -N \"http://localhost:3001/events/search_records?name=Coret\"\n```\n\nExpected stream:\n\n```text\nevent: page\ndata: {...}\n\nevent: page\ndata: {...}\n\nevent: done\ndata: {}\n```\n\n---\n\n# 7. Heartbeat Test\n\nLeave SSE open for 15+ seconds — expect periodic keep-alive lines:\n\n```text\n: heartbeat\n```\n\n---\n\n# 8. Chunked HTTP Streaming\n\n```bash\ncurl -N -X POST http://localhost:3001/stream/search_records \\\n-H \"Content-Type: application/json\" \\\n-d '{\"name\":\"Jansen\"}'\n```\n\nExpected (newline-delimited JSON):\n\n```text\n{\"query\":{...},\"response\":{\"number_found\":...,\"docs\":[...]}}\n{\"query\":{...},\"response\":{\"number_found\":...,\"docs\":[...]}}\n```\n\n---\n\n# 9. MCP Initialize\n\n```bash\ncurl -X POST http://localhost:3001/ \\\n-H \"Content-Type: application/json\" \\\n-H \"Accept: application/json, text/event-stream\" \\\n-d '{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 1,\n  \"method\": \"initialize\",\n  \"params\": {\n    \"protocolVersion\": \"2025-03-26\",\n    \"capabilities\": {},\n    \"clientInfo\": { \"name\": \"test\", \"version\": \"1.0\" }\n  }\n}'\n```\n\n---\n\n# 10. MCP List Tools\n\n```bash\ncurl -X POST http://localhost:3001/ \\\n-H \"Content-Type: application/json\" \\\n-H \"Accept: application/json, text/event-stream\" \\\n-d '{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 2,\n  \"method\": \"tools/list\"\n}'\n```\n\n---\n\n# 11. MCP Call Tool\n\n```bash\ncurl -X POST http://localhost:3001/ \\\n-H \"Content-Type: application/json\" \\\n-H \"Accept: application/json, text/event-stream\" \\\n-d '{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 3,\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"search_person\",\n    \"arguments\": { \"name\": \"Jansen\" }\n  }\n}'\n```\n\n---\n\n# Redis Testing\n\n## Start Redis\n\n```bash\nredis-server\n```\n\nRestart the MCP server. Expected in `/health`:\n\n```json\n{ \"redis\": true }\n```\n\n## Without Redis\n\nStop Redis and restart. Expected:\n\n```json\n{ \"redis\": false }\n```\n\n---\n\n# Common Commands\n\n## Regenerate after API changes\n\n```bash\nnpx tsx generate.ts\n```\n\n## Restart server\n\n```bash\nnpx tsx server.ts\n```\n\n---\n\n# Troubleshooting\n\n## Generated files missing\n\n```bash\nnpx tsx generate.ts\n```\n\n## Port already in use\n\n**Linux / macOS:**\n\n```bash\nlsof -i :3001\nkill -9 <PID>\n```\n\n**Windows:**\n\n```powershell\nnetstat -ano | findstr :3001\ntaskkill /PID <PID> /F\n```\n\n## Redis not connecting\n\nServer runs normally without Redis. Check `REDIS_URL` in `.env`.\n\n## Rate limit errors (429)\n\nThe 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.\n\n---\n\n# Recommended Production Upgrades\n\n* HTTPS reverse proxy (nginx / caddy)\n* PM2 or systemd process manager\n* Structured JSON logging (pino / winston)\n* Request tracing (OpenTelemetry)\n* Auth middleware if server is public-facing\n* Shared Redis for multi-instance deployments\n\n---\n\n# Version\n\n```text\nv1.0\n```\n\nSchema-perfect OpenAPI-generated MCP server for Open Archieven.\n","readmeFilename":"README.md"}