Search LOC digital collections, Chronicling America newspapers (full OCR), and LC Subject Headings.
Search LOC digital collections, browse Chronicling America newspapers with full OCR text, and look up LC Subject Headings via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://libofcongress.caseyjhand.com/mcp
Library of Congress digital collections, Chronicling America newspaper archives, and LC Subject Headings (LCSH) authority data. Search items and newspaper pages, retrieve full item metadata and OCR text, resolve LCSH subject terms, and browse curated collections from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
| Tool | Description |
|---|---|
libofcongress_search | Search LOC digital collections by keyword with format, date range, subject, location, and collection filters. |
libofcongress_get_item | Retrieve full metadata for a specific LOC digital item — contributors, subjects, rights, formats, and resource links. |
libofcongress_search_newspapers | Search historical newspaper pages in the Chronicling America corpus with OCR excerpts. |
libofcongress_get_newspaper_page | Retrieve the full OCR text and metadata for a specific newspaper page. |
libofcongress_search_subjects | Search Library of Congress Subject Headings (LCSH) by keyword. |
libofcongress_browse_collections | List and browse LOC curated digital collections, optionally filtered by keyword. |
| Resource | Description |
|---|---|
libofcongress://item/{+item_id} | LOC digital item metadata by ID — stable URI for injecting item context into agent conversations. |
All resource data is also reachable via libofcongress_get_item. Use libofcongress_search to discover item IDs first.
libofcongress_search toolphoto, map, newspaper, manuscript, audio, film, book, notated-music), inclusive year range (date_start/date_end), subject heading (use libofcongress_search_subjects for the exact LCSH spelling), and geographic locationcollection_slug scopes the search to one curated collection (slug from libofcongress_browse_collections) — mutually exclusive with format; an unrecognized slug returns collection_not_found on page 1notice field with recovery hints, echoing the applied filtersis_item — true for catalog items whose id resolves via libofcongress_get_item, false for non-item results (collections, exhibit/guide pages, newspaper pages), whose url should be opened insteadlibofcongress_get_item toolWashington, George, 1732-1799 (Author)), LCSH subject headings, cataloger notes, summary, languages, locations, rights information, physical description, call number, former IDs, original/online formats, and access_restrictedresource_links (deduplicated from nested upstream files[] arrays) carries downloadable digital file URLs (TIFF/JPEG/PDF); related_items lists related LOC record IDs or URLs, normalized to strings whichever form LOC sends — both render in full on structuredContent and content[], never truncatedsn95047246/1935-09-05/ed-1); the returned url is always an absolute https:// URLlibofcongress_search_newspapers toolstates — every state LOC indexes the title under, in LOC order; a title indexed against its circulation area lists severalurl field needed by libofcongress_get_newspaper_page — do not construct these URLs manuallynotice with recovery suggestions (broaden the date range, drop the state filter, historical-OCR caveat)libofcongress_get_newspaper_page toolurl field from a libofcongress_search_newspapers result — validates the URL prefix before any outbound request and rejects anything else as invalid_page_urlnewspaper_title, date, place_of_publication, states, edition, the page's sequence, and the issue's page count (segment_count) — from the same single request; fields LOC doesn't send are omittedtile.loc.gov) and reads plain text from the full_text fieldocr_available: false when the page has no digitized text (image-only batch) — a data property, not an errorocr_available is true but the text service returns nothing, a notice discloses the retrieval miss, distinct from a genuinely image-only pageq= params from fulltext URLs to avoid tile.loc.gov 404s (a known LOC API quirk)libofcongress_search_subjects toollabel verbatim in libofcongress_search's subject filter — LCSH uses inverted forms ("Photography, Aerial", "World War, 1939-1945") that differ from natural languagelibofcongress_search with it as the subject filter and read totallimit) and filters to true LCSH headings, so a heading ranked below name-authority records isn't reported as a false emptylibofcongress_browse_collections toolslug — pass it to libofcongress_search as collection_slug to search inside that collectionlibofcongress://item/{+item_id} resourcelibofcongress_get_item, as application/jsonitem_id comes from a libofcongress_search result's id field, or from libofcongress_get_itemlibofcongress://item/sn95047246/1935-09-05/ed-1); percent-encoded slashes (%2F) also resolveBuilt on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Library of Congress-specific:
Agent-friendly output:
notice field with recovery hints — echoes the applied filters and suggests how to broadentotal, page, pages, has_next), capped at LOC's ~100,000-item retrieval ceiling, with a notice disclosing how to page past itocr_available and is_item discriminator fields let callers branch on data availability without parsing textA public instance is available at https://libofcongress.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"libofcongress-mcp-server": {
"type": "streamable-http",
"url": "https://libofcongress.caseyjhand.com/mcp"
}
}
}
Add the following to your MCP client configuration file.
{
"mcpServers": {
"libofcongress-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/libofcongress-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_SESSION_MODE": "stateless",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"libofcongress-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/libofcongress-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_SESSION_MODE": "stateless",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"libofcongress-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "MCP_SESSION_MODE=stateless",
"ghcr.io/cyanheads/libofcongress-mcp-server:latest"
]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
LOC_USER_AGENT for polite access.git clone https://github.com/cyanheads/libofcongress-mcp-server.git
cd libofcongress-mcp-server
bun install
cp .env.example .env
# edit .env if you want to set LOC_USER_AGENT or LOC_REQUEST_DELAY_MS
All configuration is validated at startup via Zod schemas in src/config/server-config.ts.
| Variable | Description | Default |
|---|---|---|
LOC_USER_AGENT | User-Agent header sent with LOC API requests. LOC recommends a descriptive value for polite access. | libofcongress-mcp-server/0.3.0 |
LOC_REQUEST_DELAY_MS | Delay in milliseconds between LOC API requests to stay under the 20 req/min rate limit. | 3100 |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | Port for HTTP server. | 3010 |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_SESSION_MODE | HTTP session mode. This server is explicitly stateless. | stateless |
MCP_LOG_LEVEL | Log level (RFC 5424). | info |
LOGS_DIR | Directory for log files (Node.js only). | <project-root>/logs |
STORAGE_PROVIDER_TYPE | Storage backend. | in-memory |
OTEL_ENABLED | Enable OpenTelemetry instrumentation (spans, metrics, completion logs). | false |
See .env.example for the full list of optional overrides.
Build and run:
# One-time build
bun run rebuild
# Run the built server
bun run start:stdio
# or
bun run start:http
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security
bun run test # Vitest test suite
bun run lint:mcp # Validate MCP definitions against spec
docker build -t libofcongress-mcp-server .
docker run --rm -p 3010:3010 libofcongress-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/libofcongress-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools, resource, and initializes services. |
src/config | Server-specific environment variable parsing (LOC_USER_AGENT, LOC_REQUEST_DELAY_MS). |
src/mcp-server/tools | Tool definitions (*.tool.ts) — six LOC tools. |
src/mcp-server/resources | Resource definitions — libofcongress://item/{+item_id}. |
src/services/loc-api | LocApiService wrapping www.loc.gov — search, item fetch, newspaper page, collection browser. |
src/services/lc-linked-data | LcLinkedDataService wrapping id.loc.gov — LCSH subject heading suggest. |
tests/ | Unit and integration tests mirroring src/. |
See CLAUDE.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storagesrc/index.tsIssues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0 — see LICENSE for details.
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
npx -y @cyanheads/libofcongress-mcp-serverMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-cyanheads-libofcongress-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/libofcongress-mcp-server"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referenceio.github.cyanheads/libofcongress-mcp-server works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.