Content
# NARA MCP Server
A Model Context Protocol (MCP) server for the [National Archives and Records Administration (NARA) Catalog API v2](https://catalog.archives.gov/api/v2). Built with pure Python stdlib — no external dependencies.
## Features
- **8 MCP tools** covering persons, military, immigration, presidential records, and more
- **SQLite caching** — repeat queries are instant and free
- **Rate limiting** — max 1 live API call per second, with automatic retry on gateway errors
- **Cross-server hints** — every military/immigration result includes clickable links to complementary TNA Discovery series and Old Bailey searches
- **GEDCOM integration** — tag searches with a GEDCOM person ID (`@I47@`) to group results by ancestor
- **Zero dependencies** — Python 3.10+ stdlib only
## Requirements
- Python 3.10+
- A NARA API key (contact [Catalog_API@nara.gov](mailto:Catalog_API@nara.gov))
## Setup
### 1. Clone and configure
```bash
git clone <repo-url>
cd NARA_MCP
```
### 2. Set your API key
```bash
export NARA_API_KEY=your_key_here
```
Or add it to your shell profile / `.env` loader of choice.
### 3. Register with Claude Code (or any MCP client)
Add to your `claude_desktop_config.json` (or equivalent):
```json
{
"mcpServers": {
"nara": {
"command": "python",
"args": ["/path/to/NARA_MCP/server.py"],
"env": {
"NARA_API_KEY": "your_key_here"
}
}
}
}
```
## Files
| File | Purpose |
| --- | --- |
| `server.py` | MCP server — all tools, caching, API logic |
| `nara_cache.db` | SQLite cache (auto-created on first run) |
| `nara_mcp.log` | Rotating log file (auto-created, max 1 MB x 3) |
| `pyproject.toml` | Package metadata |
## Tools
### `nara_search_history`
Query the local SQLite cache. **Always call this first** — cache hits are instant and free.
| Parameter | Type | Description |
| --- | --- | --- |
| `gedcom_id` | string (optional) | Filter to a specific ancestor, e.g. `@I47@` |
| `keyword` | string (optional) | Filter cached records by title or description |
---
### `nara_suggest_series`
Get NARA record group suggestions plus complementary TNA Discovery and Old Bailey links from a plain-English research context. No API call — instant.
| Parameter | Type | Description |
| --- | --- | --- |
| `context` | string (required) | e.g. `"WWI soldier born 1895 New York, immigrant from Ireland"` |
Supported categories: Civil War, Revolutionary War, naval/piracy, WWI, immigration and naturalisation, Freedmen's Bureau, Native American, Presidential.
---
### `nara_search_person`
Primary person search. Automatically generates:
- US census search links for relevant years
- Draft eligibility assessment (WWI, WWII, Civil War pension)
- Immigration links if birthplace is non-US
- Military/naval cross-server fan-out hints
- NPRC fire warning where applicable
| Parameter | Type | Description |
| --- | --- | --- |
| `forename` | string (required) | |
| `surname` | string (required) | |
| `date_from` | integer (optional) | Birth year |
| `date_to` | integer (optional) | Death year |
| `birthplace` | string (optional) | Triggers immigration links if non-US |
| `occupation` | string (optional) | Triggers military/naval fan-out if applicable |
| `record_type` | string (optional) | `military`, `immigration`, `naturalisation`, `pension`, `draft` |
| `gedcom_id` | string (optional) | Tags the cache entry — no other effect |
---
### `nara_search_records`
Broad keyword search across all 35M+ NARA catalogue records. Best for places, events, units, ships, or topics rather than specific persons.
| Parameter | Type | Description |
| --- | --- | --- |
| `query` | string (required) | |
| `collection` | string (optional) | Record Group number, e.g. `"94"` for Adjutant General |
| `date_from` | integer (optional) | |
| `date_to` | integer (optional) | |
| `level` | string (optional) | `recordGroup`, `series`, `fileUnit`, `item` |
| `gedcom_id` | string (optional) | |
---
### `nara_search_military`
Targeted military records search. Automatically selects the relevant Record Groups for the given war and includes cross-server hints for TNA WO/ADM series and Old Bailey soldier/sailor searches.
| Parameter | Type | Description |
| --- | --- | --- |
| `query` | string (required) | Person name, regiment, unit, or battle |
| `war` | string (optional) | `revolutionary`, `civil_war`, `wwi`, `wwii`, `korea`, `vietnam` |
| `date_from` | integer (optional) | |
| `date_to` | integer (optional) | |
| `gedcom_id` | string (optional) | |
**Record Groups searched by war:**
| War | Record Groups |
| --- | --- |
| `revolutionary` | RG 93, RG 15 |
| `civil_war` | RG 94, RG 109, RG 15 |
| `wwi` | RG 120, RG 163, RG 92 |
| `wwii` | RG 407, RG 147, RG 338 |
| `korea` | RG 338, RG 319 |
| `vietnam` | RG 472, RG 319 |
| *(default)* | RG 94, RG 15, RG 24, RG 45 |
---
### `nara_search_immigration`
Targeted immigration and naturalisation search across RG 36 (passenger lists 1820-1957), RG 85 (INS), and RG 21 (court naturalisation records pre-1906). Includes TNA BT 26/27 cross-reference links.
| Parameter | Type | Description |
| --- | --- | --- |
| `surname` | string (required) | |
| `forename` | string (optional) | |
| `arrival_year_from` | integer (optional) | |
| `arrival_year_to` | integer (optional) | |
| `origin_country` | string (optional) | |
| `gedcom_id` | string (optional) | |
---
### `nara_get_record`
Fetch the full catalogue description for a specific record.
| Parameter | Type | Description |
| --- | --- | --- |
| `identifier` | string (required) | Numeric NaId (e.g. `"12345678"`) or reference string |
| `gedcom_id` | string (optional) | |
---
### `nara_search_presidential`
Search Presidential Library holdings (Hoover through Obama). Includes TNA FO 371 and PREM cross-reference links for Anglo-American diplomatic research.
| Parameter | Type | Description |
| --- | --- | --- |
| `query` | string (required) | |
| `president` | string (optional) | e.g. `"truman"`, `"kennedy"`, `"reagan"` |
| `date_from` | integer (optional) | |
| `date_to` | integer (optional) | |
| `gedcom_id` | string (optional) | |
## Caching
All search results are stored in `nara_cache.db` (SQLite, created alongside `server.py`). The schema has three tables:
- **`searches`** — one row per tool call, keyed by a SHA-256 hash of the parameters
- **`records`** — one row per unique NARA record (keyed by NaId), upserted on each cache write
- **`search_records`** — many-to-many join between searches and records
Cache hits bypass the API entirely. There is currently no TTL/expiry — to refresh a result, delete the relevant row from `searches`.
## Rate Limiting
A 1-second minimum interval is enforced between live API calls. Network errors and 502/503/504 responses are retried up to 3 times with exponential backoff (2 s, 4 s).
## Cross-Server Research
This server is designed to complement two other MCP servers:
- **TNA (The National Archives)** — British records. Every military and immigration result includes direct TNA Discovery series links (WO 363, WO 372, ADM 36, BT 26, BT 27, FO 371, etc.)
- **Old Bailey Online** — Criminal proceedings 1674-1913. Military and naval results include pre-built Old Bailey search URLs filtered by relevant terms (soldier, sailor, regiment, ship).
For military or naval queries, always fan out to all three servers in parallel.
## Logging
Logs are written to `nara_mcp.log` alongside the server file. The handler rotates at 1 MB, keeping 3 backups. Log level: INFO.
## Known Limitations
- **1890 census**: Substantially destroyed by fire in 1921 — fragments survive for some counties only.
- **NPRC St Louis fire (1973)**: ~80% of Army records 1912-1960 and ~75% of Air Force records 1947-1964 were destroyed. Absence of a service record does not mean the person did not serve.
- **1960+ census**: Under the 72-year privacy rule — most recent publicly available census is 1950.
- **Old Bailey archive**: Ends at 1913 in the online edition.
## License
See repository root for licence information.
Connection Info
You Might Also Like
Train-in-Silence
The first Task-Aware MCP server and automated VRAM calculator for LLM...
stacklit
108,000 lines of code. 4,000 tokens of index. One command makes any repo...
AppClaw
AI-powered mobile automation agent — describe what you want in plain...
pdf-mcp
Production-ready MCP server for PDF processing with intelligent caching....
kotadb
Local-only code intelligence API for AI developer workflows (Bun +...
gemini-api-docs-mcp
A remote HTTP MCP server for searching Google Gemini API documentation.