@cyanheads/smithsonian-mcp-server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@@cyanheads/smithsonian-mcp-serversearch for Van Gogh paintings in the Smithsonian collection"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Public Hosted Server: https://smithsonian.caseyjhand.com/mcp
Overview
Smithsonian Open Access catalog — 14.5 million objects across 20+ museums, with CC0 images for the 5.2 million that carry them. Search by free text or exact category, browse by museum, culture, date, or topic, and discover cross-collection connections from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
Tools
Tool | Description |
| Search across 14.5M objects by text query with optional filters (museum, type, date term, culture, place, topic, name, online-only, CC0). Returns curated summaries with total count. |
| Enumerate the valid term vocabulary for an indexed filter field (unit_code, culture, place, date, online_media_type, topic). Call before filtering to avoid empty results from invalid values; pass |
| Fetch a normalized catalog metadata projection for an object by ID: title, dates, materials, dimensions, exhibition history, credit line, and identifiers. |
| Return all CC0-licensed images for an object at multiple resolutions (thumbnail, screen, high-res JPEG/TIFF). Only CC0 images returned, never an empty list — a distinct error reason names why, whether the object has nothing digitized, only non-image media, or only restricted images. |
| Browse objects within one exact category (museum, culture, period, medium, topic) with total count, a page of objects, and museum breakdown. Requires an exact indexed category term. |
| Discover cross-collection objects related to an anchor, matched on shared culture, named-party, topic, and period signals. |
Related MCP server: swiss-cultural-heritage-mcp
Capability reference
smithsonian_search_objects tool
Free-text search over 14.5M objects from 20+ museums
Filters: museum unit code, object type, indexed date term (
1920s,500-1500,21st century,-2500), culture, geographic place, subject topic, named party (name), online-only, CC0-onlytopicandnameare hard indexed constraints, not free text —topic: "Quilts"matches 1,134 objects where the bare word matches 2,677, andname: "Warhol, Andy"matches 421 against 715Returns curated summaries: title, date, museum, object type, thumbnail URL, CC0 flag,
record_idUse
start+rowsfor standard pagination (offset-based, max 100 per page)
smithsonian_list_terms tool
Fields:
unit_code,culture,place,date,online_media_type,topic— a controlled vocabulary, often plural (e.g.Paintings, notPainting); ground filter values here before searching or browsingcontainsfilters the vocabulary by a case-insensitive substring — resolves a guessed value (e.g.greek→Greek, Attic) in one call; forunit_codeit also matches museum names (National Air and Space→NASM), and eachunit_codeterm comes back with alabelsmap of its museum namePaginate with
start+rows(default 50, max 100 per page);topic(133k terms) andplace(114k) are large enough to pair withcontainsNo per-term object counts are available upstream — only the term values themselves
Each field's vocabulary is cached for
SMITHSONIAN_TERMS_CACHE_TTL_SECONDS(default 3600 seconds,0disables) — upstream ignores paging and returns the whole set on every call, so paging a large vocabulary uncached re-downloads it each timeobject_typeis not enumerable here — harvest its values from theobject_typefield insmithsonian_search_objectsresults
smithsonian_get_object tool
Input:
record_idfromsmithsonian_search_objects— do not construct IDs manuallyReturns the exposed catalog fields: title, dates (all labeled), makers (with roles), materials, dimensions, place associations, culture terms, topic/subject terms, exhibition history, accession identifiers, credit line, rights statement
Media summary included — call
smithsonian_get_mediafor full image URLs
smithsonian_get_media tool
Only CC0-licensed images are returned, never restricted content
Three distinct failure reasons when nothing is returnable:
no_media(nothing digitized),no_images(media exists but is entirely non-image — scanned books, 3D models, sound recordings; the recovery hint names the types present),not_cc0(images exist but none are CC0, thrown asForbidden)Each image entry includes thumbnail (~120px), screen-size (~800px), and high-resolution JPEG/TIFF URLs with pixel dimensions
Use
smithsonian_search_objectswithfilters.cc0_only: trueto find objects with downloadable CC0 images before calling this tool
smithsonian_browse_category tool
Five modes:
museum(by unit code, e.g."NASM"— matched exactly, not by museum name),culture(e.g."Aztecs"),period(indexed date term, e.g."1940s"or"500-1500"),medium(object type, e.g."Paintings"),topic(subject term, e.g."Quilts")valuemust be an exact indexed category term — resolvemuseum,culture,period, andtopicvocabulary withsmithsonian_list_termsfirst;object_typeis not enumerable there, so harvest it fromsmithsonian_search_objectsresultsReturns total count, a page of sample objects, and a museum breakdown showing which institutions hold matching items (computed from the current page)
Use
start+rowsfor standard pagination (offset-based,start = page × rows, max 50 per page) — adjacent pages retrieve the objects a capped sample omitsA category value that matches nothing throws
invalid_categorywith a mode-specific recovery hint: a value outside the vocabulary gets the exactsmithsonian_list_termscall that resolves it, and a value the index enumerates but that matches no objects is named as such and routed elsewhereFor open-ended or topic discovery, use
smithsonian_search_objectsinstead — this tool requires an exact category value
smithsonian_find_related tool
Matches shared culture, named-party, topic, and period+type metadata signals against the wider catalog; cross-museum discovery is the differentiator — an NASM aerospace anchor may surface related objects from NMNH, SAAM, and NMAH
The named-party signal carries the catalog's own role for the party (
maker,collector,donor,issuing authority, …) rather than a fixedmakerlabel, prefers the indexednamefacet as a hard filter when the record has one, and is dropped when its value only repeats the culture signalThe topic signal is a hard
topic:filter, so every object it tags carries that subject term rather than merely mentioning the wordsimilarity_signalson each result names every metadata term that connected it to the anchor — an object surfaced by more than one signal carries all of themPage with
start— a 0-indexed offset into the interleaved related set,start = page × limit; each signal is reachable to a depth of 5,000 (fetched in ≤1,000-row chunks — a deeper page can shift an object by a bounded amount near a seam), and a truncated response reportstruncationCeilingas an upper bound on the reachable related poolsignals[]breaks the fan-out down per signal:row_countis that signal's true upstream size (uncapped, so it can exceed the 5,000 reach) andsearch_continuationis the exactsmithsonian_search_objectsinput that retrieves the signal's full match set at any depth — the retrieval path past this tool's per-signal reach
Features
Built 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.
Smithsonian-specific:
Wraps the Smithsonian Open Access API (14.5M objects across 20+ museums, 5.2M carrying CC0 media) with a free
api.data.govkeyCC0 gating on
smithsonian_get_media— only open-access images returned, never restricted contentGraceful degradation in
smithsonian_find_related— a failure in one metadata signal doesn't abort the restResponse normalization across heterogeneous museum metadata schemas
Agent-friendly output:
has_mediaon every object summary — agents can gate image download calls without an extra lookup (theis_cc0flag is the metadata license, which the Open Access corpus carries almost everywhere)Typed error reasons (
no_results,invalid_filter,not_found,no_media,no_images,not_cc0,invalid_id) with recovery hints for each casesimilarity_signalson related-object results let agents explain why objects were surfacedtotal_counton all search responses enables agents to communicate result scope before paginating
Getting started
Public Hosted Instance
A public instance is available at https://smithsonian.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"smithsonian-mcp-server": {
"type": "streamable-http",
"url": "https://smithsonian.caseyjhand.com/mcp"
}
}
}Self-Hosted / Local
Requires a free
api.data.govAPI key — register at https://api.data.gov/signup and setSMITHSONIAN_API_KEYin your config.
Add the following to your MCP client configuration file:
{
"mcpServers": {
"smithsonian-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/smithsonian-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"SMITHSONIAN_API_KEY": "your-api-key"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"smithsonian-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/smithsonian-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"SMITHSONIAN_API_KEY": "your-api-key"
}
}
}
}Or with Docker:
{
"mcpServers": {
"smithsonian-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "SMITHSONIAN_API_KEY=your-api-key",
"ghcr.io/cyanheads/smithsonian-mcp-server:latest"
]
}
}
}For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 SMITHSONIAN_API_KEY=your-api-key bun run start:http
# Server listens at http://localhost:3010/mcpPrerequisites
Bun v1.4.0 or higher (or Node.js v24+).
A free
api.data.govAPI key — register at https://api.data.gov/signup. Approval is instant.
Installation
Clone the repository:
git clone https://github.com/cyanheads/smithsonian-mcp-server.gitNavigate into the directory:
cd smithsonian-mcp-serverInstall dependencies:
bun installConfigure environment:
cp .env.example .env
# Edit .env and set SMITHSONIAN_API_KEYConfiguration
Variable | Description | Default |
| Required. Free API key from api.data.gov/signup. | — |
| Smithsonian Open Access API base URL. |
|
| Seconds to cache each indexed field's term vocabulary. |
|
| Transport: |
|
| Port for HTTP server. |
|
| Session mode: |
|
| Auth mode: |
|
| Log level (RFC 5424). |
|
| Directory for log files (Node.js only). |
|
| Storage backend. |
|
| Enable OpenTelemetry instrumentation. |
|
See .env.example for the full list of optional overrides.
Running the server
Local development
Build and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpRun 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
docker build -t smithsonian-mcp-server .
docker run --rm -e SMITHSONIAN_API_KEY=your-api-key -p 3010:3010 smithsonian-mcp-serverThe Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/smithsonian-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Directory | Purpose |
|
|
| Server-specific environment variable parsing ( |
| Tool definitions ( |
| Smithsonian Open Access API client, normalization, and type definitions. |
| Unit and integration tests. |
| Design document and directory tree. |
Development guide
See CLAUDE.md / AGENTS.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageRegister new tools via the barrel in
src/mcp-server/tools/definitions/index.tsWrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
This server cannot be deployed
Maintenance
Related MCP Connectors
Unlock a world of art with the Met Museum MCP! Use the 'search_artworks' API to find stunning
Openverse MCP — Creative-Commons-licensed image + audio search.
Search the Met collection, browse by department or update date, fetch full records and CC0 images.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides AI assistants with access to search, explore, and analyze over 3 million collection objects from the Smithsonian Institution's museums. Enables finding objects currently on exhibit, retrieving detailed metadata, high-resolution images, and 3D models from America's national museums.62 npm10MIT
- AlicenseAqualityAmaintenanceEnables AI-native access to Swiss cultural heritage data from SIK-ISEA (artists), Nationalmuseum (collections), and Nationalbibliothek (bibliography) via MCP tools, without authentication.1138 PyPIMIT
- AlicenseAqualityDmaintenanceAn MCP server for browsing and downloading open-licensed imagery from major museum and archive APIs including Wellcome, Met, Library of Congress, Smithsonian, and Europeana.1215 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables searching and exploring millions of items from the Smithsonian Institution's collections including artifacts, artworks, specimens, photographs, and more, using the Smithsonian Open Access API.3MIT