MCP server exposing the Irish National Archives census APIs (1821-1926) and the Irish Genealogy BMD records to LLM clients.
Strong tool definitions with comprehensive descriptions and well-structured schemas. All 10 tools have clear verb-noun naming (resolve_, search_, get_, find_, bmd_*) and detailed docstrings (avg 180+ chars). Input schemas are properly typed with Pydantic Field annotations including descriptions and constraints. Output schemas are documented in descriptions. Key strengths: parameter constraints (enums, ranges), dependency hints, and chaining IDs. Weaknesses: no error handling guidance in descriptions, no dry-run/confirmation patterns for sensitive operations, and output structure not formally documented in schema format.
Return the scan PDF URL for a BMD record. The URL is a stable API endpoint that redirects to a signed Linode storage URL valid for 30 minutes. Pass the API URL to the user as a citation; don't cache the redirected target.
Fetch the full transcription of one BMD record by ref. Returns a normalized dict with all fields from the detail page (name, date, location, parents, spouse, witnesses, etc.). The exact fields depend on record type — births include parents, marriages include both parties and witnesses, deaths include age/occupation/cause.
Search Irish Genealogy BMD (births, marriages, deaths, baptisms, burials). Covers civil registration (births from 1864, deaths from 1864, civil marriages from 1845) and a growing set of church registers (RC, CoI, Presbyterian, etc.) digitised by irishgenealogy.ie. Results are paginated and can be sorted by relevance or date. Use `bmd_get_record` to fetch the full transcription and `bmd_get_image_url` for the scan PDF.
Bridge from a census person to their birth/marriage/death records. Given a census person's ref, search for matching BMD records under plausible name variations (maiden names for females, etc.). Returns a dict of `{event_type: [results]}` keyed by birth/marriage/death/baptism/burial. This is a convenience wrapper around `bmd_search` that handles the common genealogy workflow of 'I found X in the 1911 census; show me their vital records'.
No error handling guidance in tool descriptions. Descriptions do not explain what to do if a place is not found, a person search returns no results, or an API call fails. LLMs need recovery hints like 'If no results, try broader search parameters' or 'Use resolve_place first if county is unknown'.
Output schemas not formally documented. Tool descriptions mention what fields are returned (e.g., 'ref', 'household_key', 'seen_in') but do not provide a structured schema definition. LLMs cannot reliably extract or chain results without explicit output type documentation.
No confirmation or dry-run pattern for sensitive operations. While all tools are read-only (low risk), the server lacks a pattern for future write operations. No tool demonstrates idempotency hints or destructive operation warnings.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 61 | 2026-07-28+ | v2 |
Bundle the common 'find relatives' chains around one person. - spread=0: just the household (equivalent to get_household). - spread=1: + the same person as found in adjacent census years. - spread=2: + best-guess parent-household candidates with confidence scores. Returns a tree-shaped response to minimise token usage. `parent_household_candidates` are heuristic — scores reflect surname match, county match, and plausible parental age band. The LLM should treat them as candidates to verify, not assertions.
Return everyone enumerated together on the same household form. For 1926 and 1901/1911, members are grouped by `image_group`. For pre-Famine fragments, grouping is best-effort by `first_image`. Response includes scan URLs (Form A / B / N) you can pass to the user as citation links.
Return the full normalized record for one person. By default returns only the normalized fields (~20-30 tokens of overhead). Pass `include_raw=True` to also get the underlying API row when you need fields not exposed by the normalized projection (e.g. children_born, education, deafdumb for 1911; folio_num for c19).
Return URL(s) for the scan of the requested form. The URLs are stable API endpoints — fetching one returns a 307 redirect to a signed Linode storage URL valid for 30 minutes. Pass the API URL to the user as a citation; don't cache the redirected target.
Resolve a free-text place name to a canonical (county, sub_place) tuple plus year coverage. Returns one or more candidates, each indicating which census years cover that county. Northern Ireland counties (Antrim, Armagh, Down, Fermanagh, Londonderry, Tyrone) are NOT in the 1926 census — the `available_in` field will reflect this. Use the returned `county` (canonical form) and `sub_place` directly with `search_people`.
Search people across all three Irish census APIs (1821-1926). Returns compact rows plus metadata. When `year='all'`, results from different censuses that plausibly represent the same person are merged with a `seen_in` field and `related_refs` pointing at the other matches. `related_refs` is capped at 3 — a `related_refs_truncated` count indicates additional matches. Use the returned `household_key` with `get_household` to reconstruct families; use `ref` with `get_person` for full details. Set `detail='brief'` when scanning many candidates to minimise tokens.
Pagination metadata incomplete. search_people and bmd_search accept 'page' and 'limit' but descriptions do not clarify whether total_count or next_cursor is returned, making it unclear how to detect end-of-results.
Ambiguous parameter relationships undocumented. search_people accepts both 'county' and 'place'; the description states 'place is resolved to county + sub_place automatically if county is not given', but does not clarify what happens if both are provided or if they conflict.