Search the Art Institute of Chicago collection: artworks, artists, exhibitions, and audio guides.
One address for any MCP client. No sign-in needed on this server.
6 read
Grouped by tool name. At most: only reads or looks up information.
Odel charges nothing per call. The publisher may charge for its own service.
Search the Art Institute of Chicago collection: artworks, artists, exhibitions, and audio guides via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://art-institute-chicago.caseyjhand.com/mcp
The Art Institute of Chicago's collection through the museum's public API: about 133,000 artworks, plus artists, exhibitions, and audio-guide stops. Search artworks by text, filters, and facet counts; read full records with provenance, exhibition history, and rights-aware IIIF image URLs; resolve artists to ids; find exhibitions by topic or date; search audio-guide transcripts. Runs without an API key, as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
| Tool | Description |
|---|---|
artic_search_artworks | Search artworks by text and filters, with facet counts and date sorting |
artic_get_artworks | Fetch full records for up to 10 artworks: description, provenance, histories, image URLs with rights status, related media |
artic_search_artists | Find artists, cultures, and organizations by name or id, with life dates, artwork counts, and sample works |
artic_search_exhibitions | Search past, current, and upcoming exhibitions by text and date |
artic_search_audio_guide | Search audio-guide stops by text: title, MP3 URL, and transcript |
artic_lookup_vocabulary | List the values a search filter accepts, with artwork counts |
| Resource | Description |
|---|---|
artic://artworks/{id} | One artwork record as JSON, with the API license text and description attribution |
artic_get_artworks returns the same record for clients that don't surface resources.
artic_search_artworks toolquery (every word must match; "exact phrase", -exclude, and a | b work) plus filters artist, artist_id, department, artwork_type, style, subject, classification, material, technique, theme, place_of_origin, gallery, year_from / year_to (date-span overlap, negative for BCE), public_domain_only, on_view_only, and has_image, combined with ANDsort is relevance, date_asc, or date_desc, and sort_applied reports popularity when relevance had no query textfacets adds the top 15 values for up to seven fields (artist rows carry artist_id); limit: 0 returns counts onlyartic_get_artworks toolids per call (artwork page URLs are read as their id); sections picks the heavy text: description and provenance by default, plus exhibition_history, publication_history, and cataloguemissing_ids for ids the museum doesn't have and deferred_ids for records held back to keep the response under about 100,000 bytesinclude_related_media (default on) loads up to 20 linked lectures and audio stops per call; description_attribution appears whenever CC BY description text is returnedartic_search_artists toolquery (all name words must match) or up to 25 ids, not both; query mode adds artists_only (default true), born_from / born_to, and up to 25 agents per pageartwork_count, up to three sample_works (the museum's highlights first), life years, and alt_names; ids mode reports missing_idsartic_search_exhibitions toolquery, when (current, upcoming, past, or the default any), and date_from / date_to (YYYY-MM-DD, matched by run overlap); up to 25 per page, pages 1–40sort is relevance, start_desc, or start_asc, defaulting to relevance with a query and start_desc without; status is the museum's label and doesn't say whether a show is open (when does)artist_ids, and the artworks shown, when the museum lists themartic_search_audio_guide toolquery is required and matches stop titles and transcripts (every word); up to 20 stops per page (default 5)title, audio_url (MP3), and transcript but no artwork id; every response carries license_text and source_citation (content is for noncommercial educational and personal use)artic_lookup_vocabulary toolvocabulary is one of department, artwork_type, style, subject, classification, material, technique, theme, place_of_origin, or gallery; optional contains substring (ignoring case and accents, so applique finds appliqué (technique)), public_domain_only, and up to 100 values (default 25)artwork_count, in the exact form the artic_search_artworks filter of the same name accepts; filter_param names that filterartic://artworks/{id} resource{ artwork, license_text, description_attribution?, notice? } as application/json, where artwork is the artic_get_artworks record with its default sections and related mediaartwork_not_found; ids come from artic_search_artworksBuilt 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.
Art Institute-specific:
api.artic.edu/api/v1); IIIF image URLs are built from each record (843 px for every image, 1686 px and a IIIF manifest for public-domain works), never fetcheddate_display stays the authorityAgent-friendly output:
image.rights (public_domain / in_copyright) on every image, with the 1686 px URL only where reuse is allowed; the API's license_text verbatim; description_attribution when CC BY text is returned; source_citation on audio-guide resultsartic_get_artworks reports missing_ids and deferred_ids, and when a secondary lookup (related media, artist counts) fails, the primary records still return with a notice naming what is missingtotalCount, has_more, next_page, and a notice for the next page, the 1,000-match ceiling, or the filter to loosen after zero hitsThe Art Institute of Chicago licenses its API data by surface, and the server passes the API's own license_text through with every artwork, artist, exhibition, and audio-guide result:
| Content | Terms |
|---|---|
| Artwork metadata, artists, exhibitions, vocabulary terms, related media | CC0 |
Artwork description text | CC BY 4.0: credit the Art Institute of Chicago and cite the record's web_url |
| Artwork images | Reusable only for public-domain works (image.rights: "public_domain", CC0); other images need a rights check |
| Audio-guide content | Noncommercial educational and personal use, with copyright notices kept and the source cited |
This server is an independent project and is not affiliated with or endorsed by the Art Institute of Chicago.
rate_limited.description, and in a general sample 94% lack provenance. About 1% of artists have a biography, and there is no nationality field, only artist_display prose.gelatin silver (developing-out-paper) pr). Pass values as artic_lookup_vocabulary lists them.<script>; the call fails as request_blocked.A public instance is available at https://art-institute-chicago.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"art-institute-chicago-mcp-server": {
"type": "streamable-http",
"url": "https://art-institute-chicago.caseyjhand.com/mcp"
}
}
}
Every caller of the hosted instance shares one api.artic.edu request budget of 50 requests a minute. For sustained use, run your own instance.
Add the following to your MCP client configuration file. No API key is needed; AIC_CONTACT tells the museum how to reach you (see Configuration).
{
"mcpServers": {
"art-institute-chicago-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/art-institute-chicago-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"AIC_CONTACT": "you@example.com"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"art-institute-chicago-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/art-institute-chicago-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"AIC_CONTACT": "you@example.com"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"art-institute-chicago-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "-e", "AIC_CONTACT=you@example.com", "ghcr.io/cyanheads/art-institute-chicago-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
AIC_CONTACT to an email or URL.git clone https://github.com/cyanheads/art-institute-chicago-mcp-server.git
cd art-institute-chicago-mcp-server
bun install
cp .env.example .env
# edit .env and set AIC_CONTACT
| Variable | Description | Default |
|---|---|---|
AIC_CONTACT | Email or URL the museum can reach, sent in the AIC-User-Agent header. Printable ASCII only; the server refuses to start otherwise. Set your own for any deployment. | https://github.com/cyanheads/art-institute-chicago-mcp-server |
AIC_REQUESTS_PER_MINUTE | Outbound requests per minute to api.artic.edu, 1–600. Stays under the API's published limit of 60; raise it only if the museum grants a higher one. | 50 |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | HTTP server port. | 3010 |
MCP_SESSION_MODE | HTTP session mode: stateless, stateful, or auto. .env.example and the Docker image set stateless. | auto |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, warning, error, etc.). | info |
LOGS_DIR | Directory for log files (Node.js only). | <app-root>/logs |
STORAGE_PROVIDER_TYPE | Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1. | in-memory |
OTEL_ENABLED | Enable OpenTelemetry. | false |
See .env.example for every server setting and the common framework overrides.
Build and run the production version:
# One-time build
bun run rebuild
# Run the built server
bun run start:http
# or
bun run start:stdio
Run checks and tests:
bun run devcheck # Lints, formats, type-checks, and more
bun run test # Runs the test suite
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point: registers the tools and resource, sets the server instructions, and starts and stops the API service. |
src/config | AIC_CONTACT and AIC_REQUESTS_PER_MINUTE parsing and validation with Zod. |
src/mcp-server/tools | Tool definitions (*.tool.ts) and the artwork output schema they share. |
src/mcp-server/resources | The artic://artworks/{id} resource. |
src/services/aic | Art Institute API client: pacing, retries, response cache, HTML-to-text, IIIF URL construction, and the artwork and artist record builders. |
tests/ | Unit and integration tests, mirroring the src/ structure. |
See CLAUDE.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for logging, ctx.enrich for paging and noticessrc/mcp-server/*/definitions/index.tsIssues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.