Skip to main content
Glama
chandhoke

archival-imagery-mcp

by chandhoke

archival-imagery-mcp

An MCP server for browsing and downloading open-licensed imagery from six major museum and archive APIs. Built for editorial projects that need authored, archival visual material instead of AI-generated stock.

License: MIT Node 18+ MCP

What this is

When Claude or any other MCP-compatible client needs imagery for an editorial project — a service site, a long-form article, a brand book, a deck — generating images from scratch usually produces something that reads as AI. For brands with editorial bona fides, that signal is fatal.

This server gives the assistant a different option: search the world's open-access museum collections for authored, attributed, often-centuries-old imagery and download it straight into the project's public/ folder. Most results are CC0, CC-BY, or Public Domain Mark — usable with no licensing friction.

Related MCP server: IIIF MCP Server

Sources

Source

Coverage

API Key

License Defaults

Wellcome Collection

UK. Medical, scientific, esoteric, astrological history. ~250k items.

No

CC-BY / PDM

Met Museum

US. Open Access program. ~470k objects, all CC0 when public domain.

No

CC0

Library of Congress

US. Photos, manuscripts, maps, prints, newspapers, film. ~1M items.

No

Mostly PD

Smithsonian Open Access

US. 4.5M+ CC0 items across 21 museums.

Free

CC0

Europeana

EU aggregator — British Library, Louvre, full Rijksmuseum collection, plus 4000+ institutions.

Free

Mixed (filterable)

Note on Rijksmuseum: the Rijksmuseum's REST API was deprecated in 2024 in favour of OAI-PMH (an XML harvesting protocol designed for institutional bulk-download, not query-by-keyword). Rather than re-implement on a less query-friendly protocol, this server intentionally omits direct Rijksmuseum support. Europeana fully indexes the Rijksmuseum collection — query it via europeana_search with provider="Rijksmuseum".

Installation

No install step needed if you have Node 18+ — just point your MCP client at npx:

{
  "mcpServers": {
    "archival-imagery": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "archival-imagery-mcp"],
      "env": {
        "SMITHSONIAN_API_KEY": "your-key-here-or-omit",
        "EUROPEANA_API_KEY": "your-key-here-or-omit"
      }
    }
  }
}

Or install once globally:

npm install -g archival-imagery-mcp

Then use "command": "archival-imagery-mcp" (no args needed) in your config.

API keys are all optional — Wellcome, Met, and Library of Congress work without keys. Smithsonian and Europeana tools return a helpful error message with the signup URL if their key is missing.

From source (for development / custom builds)

git clone https://github.com/chandhoke/archival-imagery-mcp.git
cd archival-imagery-mcp
npm install

Then point your MCP config at the local path:

{
  "mcpServers": {
    "archival-imagery": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/archival-imagery-mcp/index.mjs"]
    }
  }
}

Getting the optional API keys

All free, all take under 2 minutes:

  • Smithsonian: api.data.gov/signup/ — email confirmation. The same key works for NASA, NOAA, FCC, and most US government APIs.

  • Europeana: pro.europeana.eu/page/get-api — instant. Covers British Library, Rijksmuseum, Louvre, and 4000+ other institutions in one endpoint.

Tools (12 total)

Search & retrieval

Tool

Source

Needs Key

wellcome_search

Wellcome

wellcome_get_work

Wellcome

wellcome_image_url

Wellcome (utility)

met_search

Met

met_get_object

Met

loc_search

Library of Congress

loc_get_item

Library of Congress

smithsonian_search

Smithsonian

smithsonian_get_object

Smithsonian

europeana_search

Europeana

europeana_get_record

Europeana

Shared utility

Tool

Purpose

download_image

Save any image URL (from any of the above) to a local path. Creates parent dirs automatically.

Usage examples (natural language)

Once installed, just describe what you want and the assistant picks the right tool:

"Find Indian astrology pieces at the Met that we could use on /method — show me 5."

"Search Wellcome for nakshatra diagrams and save the best two to my project's public/brand/ folder."

"Use Europeana with provider='Rijksmuseum' to find Vermeer paintings — I want a portrait for the about page."

"Use Europeana to find anything from the British Library tagged 'Sanskrit manuscript' — only CC0/CC-BY please."

Attribution

When using imagery from any of these sources in published work, always check the per-item license (returned with every result) and follow its attribution requirements. Most CC-BY items only need a short credit line:

Imagery courtesy of [Source] (CC BY 4.0).

CC0 / Public Domain Mark items have no attribution requirement but crediting the source is good practice.

Architecture

  • Single-file MCP server (index.mjs), ~400 lines

  • Native fetch (Node 18+), no HTTP library dependency

  • Only one dependency: @modelcontextprotocol/sdk

  • No telemetry, no persistent state, no auth required for the server itself

  • Stateless — every tool call hits the upstream API fresh

Extending

To add another source (e.g. New York Public Library Digital Collections, DPLA, Gallica):

  1. Add a section under // ========================================================================= with xyzSearch, xyzGetObject functions

  2. Add an env-var helper if it needs a key (use the existing requireKey pattern)

  3. Add entries to the TOOLS array with clear descriptions

  4. Add entries to the HANDLERS map

~50 lines per new source.

License

MIT © Harpreet Chandhoke

This server is a client for third-party APIs. Each source has its own terms — respect them in your usage. The MIT license applies only to this server code, not to the content retrieved.

Available Tools

12 tools
download_imageA

Download any image URL to a local file path. Parent directories are created automatically. Works with images returned from any of the above sources.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYes
savePathYesAbsolute local path, e.g. 'C:/path/to/project/public/brand/asset.jpg'

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. It does disclose a useful side-effect (parent directories are created automatically) and broad source compatibility, but does not mention return values, error handling, or whether existing files are overwritten. It is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences with no wasted words. The primary purpose is front-loaded, and each sentence adds a distinct piece of information (what, side-effect, source compatibility).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple, but because there is no output schema and no annotations, the description should explain what the tool returns or how success/failure is indicated. It does not mention the return value or error scenarios, leaving a gap. The description is clear but not fully complete for an agent to invoke without assumptions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%, with only savePath having a description. The description clarifies the overall function (url to local file path) but does not add specific details about the URL format or constraints beyond what is already implied by the tool name and schema. It compensates partially.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool downloads any image URL to a local file path, using a specific verb and resource. It also distinguishes itself from the sibling search/get tools by noting it works with images returned from those sources.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context by stating it works with images from any of the above sources, which guides the agent to use this tool when a URL is available. However, it does not explicitly state when not to use it or name alternative tools for other scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

europeana_get_recordA

Fetch a Europeana record by ID (e.g. '/2048128/618580'). Requires EUROPEANA_API_KEY.

ParametersJSON Schema
NameRequiredDescriptionDefault
recordIdYes

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden. It discloses the API key requirement and gives an example ID, but does not mention return format, error handling, or whether the operation is read-only. For a fetch tool this is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the verb and resource. The API key note is concise and relevant. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with one parameter, no output schema, and no annotations, the description covers the core purpose, required auth, and an ID example. It lacks explicit return-value details, but for a fetch operation the return is implied. Overall, it's sufficient but not exhaustive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has no description for recordId (0% coverage), but the description provides an example value ('/2048128/618580') that clarifies the expected format. This adds meaning beyond the schema's bare type string, though it could further explain where to find the ID.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action ('Fetch') on a specific resource ('a Europeana record by ID'), with an example ID format. This distinguishes it from the sibling europeana_search tool, which is for searching rather than fetching by ID.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is for retrieving a known record by ID, which contrasts with the search tool. It also notes the API key requirement, which is a prerequisite. However, it doesn't explicitly state 'use this when you have an ID' or mention alternatives, so it's clear context without explicit exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

loc_get_itemA

Fetch a Library of Congress item by full URL (e.g. 'https://www.loc.gov/item/2003663891/'). Returns metadata and all image file URLs.

ParametersJSON Schema
NameRequiredDescriptionDefault
itemUrlYes

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It states what the tool returns ('metadata and all image file URLs') and gives an example URL format, but does not disclose potential error behaviors, URL validity requirements, or any side effects. This is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise, front-loaded sentences. The verb 'Fetch' starts the description, and the example URL provides concrete guidance without unnecessary verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter tool, the description is largely complete: it states the purpose, input format, and return payload. However, it would be stronger if it noted behavior for invalid URLs or explicitly linked to the download_image sibling for handling returned image URLs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description effectively documents the single parameter by defining it as a 'full URL' and providing an explicit example. This gives the agent enough semantic understanding to construct a valid itemUrl value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action ('Fetch') and resource ('a Library of Congress item'), and specifies the key input method (by full URL). The example URL further disambiguates the tool, distinguishing it from sibling search tools like loc_search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when the agent has a full item URL, which provides clear context. However, it does not explicitly mention alternatives or exclusions, such as 'use loc_search when you only have a query'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

met_get_objectA

Fetch a Met object by numeric ID with all image URLs (primary + additionals) and metadata.

ParametersJSON Schema
NameRequiredDescriptionDefault
objectIdYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden of disclosing behavior. It does mention the return content (all image URLs and metadata), but it does not address read-only safety, error handling, or potential limitations. This is a simple fetch operation, so the risk is low, but more transparency could be provided.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with no fluff. It efficiently conveys the core action, resource, and return value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the low complexity (single parameter, no output schema), the description adequately explains the return content. However, it omits usage context and edge-case behavior, which prevents a perfect score.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description only says 'numeric ID', which merely echoes the schema's type 'number'. It does not name the parameter 'objectId' or add constraints, ranges, or examples, failing to compensate for the lack of schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool fetches a Met object by numeric ID, listing the return content (image URLs and metadata). This distinguishes it from sibling tools like met_search (search vs. fetch) and other museum get tools (specific to the Met).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no explicit guidance on when to use this tool versus alternatives. It does not mention exclusions, prerequisites, or scenarios where another tool (e.g., met_search) would be more appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

smithsonian_get_objectB

Fetch a Smithsonian object by ID with all image URLs and metadata.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden. It discloses what the tool returns (image URLs and metadata), but does not mention authentication, rate limits, error handling, or any other behavioral constraints. Basic operational facts are present, but no deeper transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence that conveys the essential purpose and output without any wasted words. Every phrase earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simplicity of the tool (one parameter, no output schema), the description covers the core purpose and main output, but lacks caveats about missing IDs, authentication requirements, or possible response limitations. It's minimally viable but leaves some context gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema only defines 'id' as a string, and the description adds no additional meaning beyond restating 'by ID'. There is no guidance on the format, source, or examples of the ID, which is a significant gap given 0% schema description coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (Fetch), the resource (Smithsonian object), and the method (by ID), while also noting the included content (all image URLs and metadata). This distinguishes it from search tools and other museum-specific get tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies that the tool is used when you have an ID and need full object details, but it does not explicitly say to use search first or provide any when/when-not alternatives. The usage context is inferred rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wellcome_get_workA

Fetch a Wellcome work by ID with all associated IIIF image URLs.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden. It discloses that this is a fetch (read-only) operation and that the response includes all associated IIIF image URLs. However, it does not describe error behavior, response format validity, or any potential rate limits, leaving some gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with no filler. Every word adds value in specifying the action, resource, and key output detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (1 parameter, no output schema), the description covers the primary purpose and the notable return behavior (IIIF image URLs). It does not explain error cases or full response structure, but these are secondary for a straightforward fetch operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It does so by indicating that the 'id' parameter is the Wellcome work identifier, but it lacks examples or format details. For a single parameter, this is adequate but minimal.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the action ('Fetch'), the target resource ('Wellcome work'), and the unique distinguishing feature (includes IIIF image URLs). This clearly differentiates it from sibling tools like wellcome_search and wellcome_image_url.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage: when you have a Wellcome work ID and need the work with its IIIF image URLs. It provides no explicit exclusions or comparisons to alternatives like wellcome_search or wellcome_image_url, so guidance is only implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wellcome_image_urlA

Build a direct Wellcome IIIF image URL at any IIIF Image API size ('1200,', ',900', 'full', etc.).

ParametersJSON Schema
NameRequiredDescriptionDefault
sizeNo1200,
iiifIdYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must carry the behavioral transparency burden. It discloses that the tool accepts arbitrary IIIF size strings and builds a direct URL. It does not detail error handling or return type, but for a simple pure URL builder, the main behavior is clearly stated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence containing all essential information, with practical examples inline. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the low complexity, no annotations, and no output schema, the description covers the primary function and size options. However, it omits explicit clarification of what 'iiifId' should be and does not state the output is a URL string, though implied. This gap prevents a perfect score.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has zero per-property descriptions (0% coverage), so the description must compensate. It thoroughly explains the 'size' parameter with examples, but leaves 'iiifId' undefined, relying on the parameter name and tool context. This partial coverage warrants a 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses the imperative verb 'Build' and the specific resource 'direct Wellcome IIIF image URL', making the function unambiguous. It also includes concrete size examples, and it is clearly distinct from sibling metadata/search tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the use case: construct a direct image URL for the Wellcome IIIF API. It does not explicitly mention alternatives like download_image or wellcome_get_work, but the context makes it clear this is for URL generation. No exclusions or when-not-to-use guidance is provided, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 12 tool updatesv0.2.1
    • First observeddownload_image
    • First observedeuropeana_get_record
    • First observedeuropeana_search
    • First observedloc_get_item
    • First observedloc_search
    • First observedmet_get_object
    • First observedmet_search
    • First observedsmithsonian_get_object
    • First observedsmithsonian_search
    • First observedwellcome_get_work
    • First observedwellcome_image_url
    • First observedwellcome_search

TDQS

A4/5.0

Scored across 12 tools

Disambiguation5/5

Each tool is clearly scoped to a specific institution and action (search vs. fetch vs. utility). The institution prefixes make it immediately clear which API a tool targets, and search/fetch pairs within each institution are unambiguous. Even the generic download_image is distinct as a utility.

Naming Consistency4/5

The naming follows a predictable {institution}_{search|get_*} pattern for the source-specific tools, with snake_case throughout. The only deviation is wellcome_image_url, which uses a noun phrase instead of a verb, but it is still recognizable and consistent in style.

Tool Count5/5

12 tools is well-scoped for a multi-institution archival imagery server. Each institution has at least a search and a fetch tool, plus a generic download utility and a IIIF URL builder. No tool feels redundant or unnecessary.

Completeness5/5

The server covers the complete lifecycle for the domain: search each institution's collections, retrieve detailed metadata and image URLs, and download images. All included institutions have both search and fetch capabilities, so there are no dead ends or obvious missing operations.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    An MCP server that enables searching and fetching openly-licensed images from Openverse with features like filtering by license type, getting image details, and finding essay-specific illustrations.
    5
    28 npm
    18
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    MCP server for searching museum collections and viewing artwork images and metadata from multiple museums, including the Met, Art Institute of Chicago, Rijksmuseum, and more.
    2
    4
    8 npm
    2
    MIT