Plugs Claude into three Library of Congress APIs: the main digital collections search (with format, date, subject, and location filters), Chronicling America's newspaper archive with full OCR text extraction, and the LC Subject Headings authority file. You get six tools that cover discovery, full metadata retrieval, and newspaper page text fetching. The newspaper tools are the standout piece. They return OCR excerpts inline during search, then pull complete ALTO XML text for individual pages, which is useful for historical research or citation work that needs the actual digitized words, not just catalog records. Also exposes a resource template for stable item references.
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
Six tools covering the Library of Congress digital holdings — general search with format/date/subject/location filters, full item retrieval, Chronicling America newspaper search with OCR, single-page full-text fetch, LCSH subject heading lookup, and curated collection browsing:
| Tool | Description |
|---|---|
libofcongress_search | Search LOC digital collections by keyword with optional format, date range, subject heading, and geographic location filters. Returns item summaries with IDs for follow-up retrieval. |
libofcongress_get_item | Retrieve full metadata for a specific LOC item — contributors, subjects, rights, physical description, resource links (TIFF/JPEG/PDF), and related items. |
libofcongress_search_newspapers | Search historical newspaper pages in the Chronicling America corpus. Returns pages with OCR text excerpts (~500 chars), publication title, date, state, and the URL needed for libofcongress_get_newspaper_page. |
libofcongress_get_newspaper_page | Retrieve the full OCR text of a specific newspaper page. Pass the url field from a libofcongress_search_newspapers result. Returns ocr_available: false when the page has no digitized text. |
libofcongress_search_subjects | Search Library of Congress Subject Headings (LCSH) by keyword. Returns controlled-vocabulary labels and URIs — use the label as the subject filter in libofcongress_search. |
libofcongress_browse_collections | List and browse LOC curated digital collections with descriptions, item counts, and slugs. Optionally filter by keyword. |
libofcongress_searchSearch the LOC digital collections with full-text keyword matching and facet filters.
photo, map, newspaper, manuscript, audio, film, book, notated-musiclibofcongress_search_subjects first to get the exact LCSH spelling"oklahoma", "washington d.c.")message field with recovery hints — echoes the applied filterslibofcongress_get_itemRetrieve the full metadata record for a specific LOC digital item.
resource_links contains URLs to downloadable digital files (TIFF, JPEG, PDF) for items with digital surrogatesrelated_items lists IDs of related LOC items for follow-up retrievalfiles[] arrayslibofcongress_search_newspapersSearch historical newspaper pages in the Chronicling America corpus via the LOC /newspapers/ endpoint.
url field needed by libofcongress_get_newspaper_page — do not construct these URLs manuallymessage with recovery suggestions (broaden date, try different keywords, historical OCR caveat)libofcongress_get_newspaper_pageRetrieve the full OCR text and metadata for a specific newspaper page.
url field from a libofcongress_search_newspapers result — validates the URL prefix before any outbound requestCONTENT attributesocr_available: false when the page has no digitized text (image-only batch) — not an error, a data propertyq= params from fulltext URLs to avoid tile.loc.gov 404s (known LOC API quirk)libofcongress_search_subjectsSearch Library of Congress Subject Headings (LCSH) via id.loc.gov.
count field indicates approximate number of LOC items carrying that heading (when available)label exactly in the libofcongress_search subject filter — LCSH uses inverted forms ("Photography, Aerial", "World War, 1939-1945") that differ from natural languagelibofcongress_browse_collectionsList and browse LOC curated digital collections.
slug — use as a partof facet value in libofcongress_search to scope searches to a single collection| Type | Name | Description |
|---|---|---|
| Resource | libofcongress://item/{item_id} | LOC digital item metadata by ID. Stable URI for injecting item context into agent conversations. Returns the same full record as libofcongress_get_item. |
All resource data is also reachable via libofcongress_get_item. Use libofcongress_search to discover item IDs first.
Built on @cyanheads/mcp-ts-core:
none, jwt, oauthin-memory, filesystem, Supabase, Cloudflare KV/R2/D1LOC-specific:
CONTENT attributes from LOC text-services responsesLocApiService for www.loc.gov and LcLinkedDataService for id.loc.govAgent-friendly output:
message field with recovery hints — echoes the applied filters and suggests how to broadentotal, page, pages, has_nextocr_available discriminator on newspaper page results so callers can branch on data availability without parsing textAdd 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_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_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"libofcongress-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"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.2.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_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 and logs to /var/log/libofcongress-mcp-server.
| 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 and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0 — see LICENSE for details.
LOC_USER_AGENTdefault: libofcongress-mcp-server/0.2.8User-Agent header sent with LOC API requests. LOC recommends a descriptive value for polite access.
LOC_REQUEST_DELAY_MSdefault: 3100Delay in milliseconds between LOC API requests to stay under the 20 req/min rate limit.
MCP_LOG_LEVELdefault: infoSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
MCP_HTTP_HOSTdefault: 127.0.0.1The hostname for the HTTP server.
MCP_HTTP_PORTdefault: 3010The port to run the HTTP server on.
MCP_HTTP_ENDPOINT_PATHdefault: /mcpThe endpoint path for the MCP server.
MCP_AUTH_MODEdefault: noneAuthentication mode to use: 'none', 'jwt', or 'oauth'.
com.mcparmory/google-search
io.github.pipeworx-io/brave-search
marcopesani/mcp-server-serper
brave/brave-search-mcp-server
com.mcparmory/google-search-console
acamolese/google-search-console-mcp