open-museum-mcp
This server provides a unified interface to search, retrieve, and cite rights-verified open-access artworks across five major museum collections.
Search artworks (
search_artworks): Query The Met, Cleveland Museum of Art, Art Institute of Chicago, Wikimedia Commons, and Europeana simultaneously or per museum, with optional filters for date range (year_min/year_max, supporting BCE as negative integers), image availability, and result limit (1–50). Only records passing strict per-museum rights verification (CC0, Public Domain) are returned.Fetch a single artwork (
get_artwork): Retrieve full normalized metadata for a specific artwork using its museum-prefixed ID (e.g.met:436535), including artist attribution, dates, medium, region, period, image URLs, and license details.Generate citations (
cite): Produce citations in three styles —full(footnotes/bibliographies),caption(image credits), andshort(inline references) — from any artwork ID.Discover random artworks (
discover_random): Retrieve a random artwork from the local cache filtered by region, period, museum, or excluded artists — useful for surfacing non-canonical works.List cached traditions (
list_traditions): View which cultural regions and historical periods are represented in the local cache, with per-museum record counts, to understand collection coverage before searching.
Provides access to open-access artworks from Wikimedia Commons, enabling searches and retrieval of normalized artwork data with rights verification.
open-museum-mcp
One search across open-access museum collections worldwide, with strict per-museum rights verification and ready-to-use citations.
The Met, Rijksmuseum, the Smithsonian, Cleveland Museum of Art, the Art Institute of Chicago, SMK (National Gallery of Denmark), the Walters, Wellcome Collection, Wikimedia Commons, and Europeana — searched together, returned in one normalized shape, with the rights gate enforced per museum so you never receive a record whose open-access status is missing or ambiguous. The list keeps growing.
See it in action first → pramod.ch/open-museum-mcp — three worked examples (cross-tradition pairing, date-windowed scan, counterpoint discovery), real records, real citations, no install required.

Who this is for
Art-history students and researchers who need cited references and rights-cleared images for papers, slides, and theses — across institutions, in one query.
Writers, educators, and journalists who want reuse-safe artwork to pair with essays, lessons, or articles, with pre-formatted attributions.
MCP / agent builders who want a small set of high-value tools (
search_artworks,get_artwork,cite) with consistent schemas across sources, instead of installing one MCP per museum.
Related MCP server: webfetch
Why I built this
I kept wanting reuse-safe artwork for my writing, and every museum's rights model is different. So I built one MCP interface that only returns records that pass per-museum verification rules, with strict deny on ambiguity. It lets me search by artist, period, region, and other fields, and pulls the image and description back in one normalized shape.
If anyone else is exploring open-access art, I hope this helps. The plan is to keep adding museums from around the world.
How this is different from single-museum MCPs
There are excellent single-museum servers (metmuseum-mcp, rijksmuseum-mcp, smithsonian-mcp). This one is the multi-museum entry point: install once, query across all sources at the same time, get a single normalized schema across them, with a license gate you can audit per museum in src/licenseGate.ts. If you only ever need one collection, install that museum's MCP. If you want comparisons across institutions, citations across periods, or rights-verified breadth — install this.
What you get
Many museums, one query. The Met, Rijksmuseum (direct), the Smithsonian, Cleveland, the Art Institute of Chicago, SMK (National Gallery of Denmark), the Walters, Wellcome Collection, the National Gallery of Art (Washington), Harvard Art Museums, the J. Paul Getty Museum, Wikimedia Commons, and Europeana are live — keyless where the museum allows it, opt-in via a free API key where required — and the list keeps growing.
Strict deny on ambiguity. Records are validated against per-museum rights rules in code. Missing or unclear indicators drop the record; nothing is defaulted to "open".
Catalog-grade metadata. A dynasty-aware date parser handles Tang, Edo, Safavid, Mughal and the rest. Regions normalize across museums. Attribution separates named artists from anonymous, workshop, "after", and attributed works. Date-range filter on
search_artworksfor queries like Dutch genre painting 1640–1680.Citation-ready output. Three citation styles (
full,caption,short) generated deterministically from the same record — paste straight into a paper, a slide caption, or an inline reference.Listable resources.
museum://{code}/{id}resources let you bookmark interesting IDs across a session.
Quick example
A search call returns license-verified results in one normalized shape:
// Tool call: search_artworks({ query: "van gogh wheat", museum: "met", limit: 1 })
{
"count": 1,
"results": [
{
"id": "met:436535",
"museum": {
"code": "met",
"name": "The Metropolitan Museum of Art",
"url": "https://www.metmuseum.org"
},
"title": "Wheat Field with Cypresses",
"artist": {
"name": "Vincent van Gogh",
"nationality": "Dutch",
"lifespan": "1853–1890",
"attributionType": "named"
},
"displayDate": "1889",
"yearStart": 1889,
"yearEnd": 1889,
"medium": "Oil on canvas",
"region": "netherlands",
"period": null,
"imageUrls": { "full": "https://images.metmuseum.org/..." },
"imageOpenAccess": true,
"metadataOpenAccess": true,
"license": {
"type": "CC0",
"rawValue": "true",
"verificationSource": "met.isPublicDomain",
"verifiedAt": "2026-04-25T12:00:00.000Z",
"confidence": "high"
},
"source": {
"apiUrl": "https://collectionapi.metmuseum.org/public/collection/v1/objects/436535",
"pageUrl": "https://www.metmuseum.org/art/collection/search/436535"
}
}
]
}Install
Want to see it work before installing? pramod.ch/open-museum-mcp walks through the three core workflows with real records and citations.
One-click
For supported clients, no JSON, no Node, no npm — pick your client:
Claude Desktop: Download
open-museum-mcp.mcpbfrom the latest release and double-click it. Claude Desktop opens the bundle and installs the server in one step.VS Code: Install in VS Code — opens VS Code with the install dialog prefilled (requires the GitHub Copilot Chat extension).
Cursor: Install in Cursor — same idea, Cursor-flavoured (MCP support is built in).
JSON config (any MCP client)
For ChatGPT with MCP, Cline, Goose, Continue, Zed, or anything else: paste this into your client's MCP config and restart. npx fetches and runs the server on first launch.
{
"mcpServers": {
"open-museum": {
"command": "npx",
"args": ["-y", "open-museum-mcp"]
}
}
}From source (for contributors)
git clone https://github.com/cfpramod/open-museum-mcp
cd open-museum-mcp
npm install
npm run buildThen point the MCP config at the built binary:
{
"mcpServers": {
"open-museum": {
"command": "node",
"args": ["/absolute/path/to/open-museum-mcp/dist/server.js"]
}
}
}Recipes
Once installed, paste one of these into your MCP client (Claude Desktop, ChatGPT with MCP, etc.) — the tools take care of the rest.
Cross-tradition pairing for an essay or slide deck
Find a 17th-century Dutch genre painting and a same-period work from East Asia I can pair as a comparison. Return citations in caption form for both.
The agent will call search_artworks with year_min: 1600, year_max: 1700 plus your two queries, then cite(id, "caption") on the picks.
Date-windowed research scan
Show me Dutch genre painting between 1640 and 1680. Six works, full citations, prefer different artists.
search_artworks({ query: "Dutch genre painting", year_min: 1640, year_max: 1680, limit: 6 }) then cite per result.
Counterpoint to a canonical work
Suggest a non-canonical Edo-period work to pair with Vermeer's Woman Holding a Balance. Explain the contrast.
search_artworks for Vermeer, then discover_random({ region: "japan", period: "edo" }) for the counterpoint, then prose from the agent grounded in both records' metadata.
Tools
Tool | Description |
| Search across registered museums. Returns only records that pass the rights gate. Supports an inclusive date-range filter via |
| Fetch a single artwork by its normalized ID (e.g. |
| Render a citation. |
| Pick one random artwork from the local cache that matches the constraints. Operates over what has already been searched and cached. Useful for breaking out of repetitive search territory. |
| List the regions and periods present in the local cache, with per-museum record counts. Lets you see where holdings are well-represented and where they're sparse. |
cite example outputs
For Van Gogh's Wheat Field with Cypresses (met:436535):
caption: "Vincent van Gogh, Wheat Field with Cypresses, 1889. Oil on canvas.
The Metropolitan Museum of Art, CC0.
https://www.metmuseum.org/art/collection/search/436535"
full: "Vincent van Gogh, Wheat Field with Cypresses. 1889. The Metropolitan
Museum of Art. CC0. https://www.metmuseum.org/art/collection/search/436535."
short: "Wheat Field with Cypresses (Vincent van Gogh, 1889)"The caption style follows museum-publication convention: comma-separated head, medium called out, terse end. The full style is suitable for footnotes and bibliographies. The short style is for inline references where you've already established context.
For anonymous works (e.g. a Tang dynasty funerary vessel), the artist field becomes "Unknown artist" in caption form.
Resources
museum://{museum_code}/{id}: read or list any indexed artwork by URI. Listable resources let you build a per-session shortlist without re-invoking tools.
Performance notes
The Met API has no batch endpoint for object retrieval. A
search_artworkscall withlimit: 10makes one search request plus up to ten parallel object fetches (eleven HTTP round trips total on a cold cache). On warm cache the search is one round trip and most objects are local.Where possible, search-side filters are pushed to the museum (
isPublicDomain=trueis sent with every Met search) so the rights gate has fewer rejections to handle.Object records are cached for 90 days (artworks don't change). Search result IDs are cached for 14 days (museums add new open-access objects regularly).
Verification model
This is the heart of the project. Each museum exposes rights information in its own way; the server's job is to decide acceptance per museum and never default to "open" on ambiguity.
Default policy: strict deny. If a record's rights signal is missing, malformed, or non-affirmative, the record is dropped and the rejection reason is logged.
Museum | Verification source | Accept condition |
The Met |
|
|
Cleveland Museum of Art |
|
|
Art Institute of Chicago |
|
|
Wikimedia Commons |
|
|
Europeana |
| exact match on the CC0 or Public Domain Mark URI; everything else (CC-BY, CC-BY-SA, NoC, InC) is rejected |
Walters Art Museum | dataset-level CC0 declaration (no per-object rights field) | the museum publishes its whole released dataset under CC0; we accept only records that are pre-1928 (latest date |
SMK (National Gallery of Denmark) |
|
|
Wellcome Collection | the |
|
National Gallery of Art (Washington) |
|
|
Harvard Art Museums |
|
|
J. Paul Getty Museum | two independent checks: the object's own | both must classify as the CC0 URI to accept an open, embeddable image; metadata-only records (object CC0, image not) are still accepted, with |
The Walters is the one INGEST source: its API closed in 2023, so it ships as a committed CC0 bundle (src/data/walters.json, regenerated by scripts/build-walters-index.ts) rather than a live API. Because the dump carries no per-object rights flag, the accept condition substitutes the museum's blanket CC0 grant plus a defensive pre-1928 + image gate — strict on the ambiguous modern tail.
Each accepted record carries:
imageOpenAccess: the artwork's image may be reused under the recorded license.metadataOpenAccess: the artwork's catalog metadata may be reused (often broader than image rights).license.type: normalized license tier (CC0,PD,CC-BY,OTHER, …). Most sources emitCC0orPD; a source with an open-access permission that isn't a standard CC licence (e.g. Harvard'simagepermissionlevel=0) is surfaced asOTHERwithimageOpenAccess: true, rather than over-claimed as CC0/PD — the rights are shown faithfully, the Open Clearance way.license.rawValue: the museum's own field value, preserved.license.verificationSource: the exact museum field that was checked (e.g.met.isPublicDomain).license.confidence:highfor unambiguous accepts (the only level emitted today).license.verifiedAt: ISO timestamp of when this verification ran.
This is what "rights-verified" means here: validated against published museum metadata using source-specific rules implemented in this repo, with strict deny on ambiguity. It is not a guarantee of third-party rights beyond what each museum's API publicly represents. See Disclaimer.
Supported museums
Museum | Code | Auth | Status |
The Metropolitan Museum of Art |
| none | ✅ v0.1 |
Cleveland Museum of Art |
| none | ✅ v0.2 |
Art Institute of Chicago |
| none | ✅ v0.2 — |
Wikimedia Commons |
| none | ✅ v0.3 |
Europeana |
| API key (free, per-user) | ✅ v0.4 |
Walters Art Museum |
| none (bundled CC0 dataset) | ✅ v0.14 |
SMK (National Gallery of Denmark) |
| none | ✅ v0.14 |
Wellcome Collection |
| none | ✅ v0.14 |
National Gallery of Art (Washington) |
| none (bundled CC0 dataset) | ✅ v0.15 |
Harvard Art Museums |
| API key (free) | ✅ v0.15 |
J. Paul Getty Museum |
| none | ✅ v0.17 — two-tier rights: collection metadata is CC0, but each image's rights are verified independently (~91k of ~168k objects have an Open Content Program image; the rest are metadata-only) |
Smithsonian Open Access |
| API key (free) | 📋 v2 |
Rijksmuseum |
| API key (free) | 📋 v2 |
On Wikimedia Commons: Commons is a federation, not a single museum. Rights are per-file. The adapter accepts only cc0 and the worldwide public-domain templates (pd, pd-art, pd-old*, pdm, pdm-*); CC-BY, CC-BY-SA, and other attribution-or-restriction licences are rejected even though they're "free", because the per-museum gate model doesn't carry the obligations they impose. Jurisdiction-scoped public-domain tokens (pd-us*, pd-1923, and similar US-only templates) are also rejected: an accepted record is stamped as a worldwide determination, so a US-only signal must not be promoted to a worldwide claim — the same strict-default-deny reason the Europeana gate rejects NoC-US. Adding Commons unlocks works whose home museums don't have public APIs (Bruegel at the Royal Museums of Fine Arts of Belgium, the National Gallery in London pre-API, regional museums worldwide) — at the cost of a thinner metadata layer than the structured-API museums provide. Region and period are not surfaced for Wikimedia records until v0.7 adds Wikidata enrichment.
On Europeana: Europeana aggregates tens of millions of records from European cultural-heritage institutions, with rights expressed as a URI from a fixed vocabulary (Europeana Rights Statements). The adapter accepts only the unambiguous public-domain URIs — CC0 (creativecommons.org/publicdomain/zero/1.0/) and the Public Domain Mark (creativecommons.org/publicdomain/mark/1.0/). Everything else (CC-BY, CC-BY-SA, CC-BY-NC, NoC-*, InC) is rejected on the same strict-default-deny grounds as the Wikimedia gate. Europeana requires a free per-user API key — register at pro.europeana.eu/get-api and set EUROPEANA_API_KEY either in your shell, in a project-root .env, or in ~/.open-museum-mcp/.env. The fetcher silently disables itself when the key is missing (the rest of the federation continues to work).
On the Getty Museum: Getty publishes its collection as Linked.Art (CIDOC-CRM) JSON-LD, not a flat REST search API — there is no keyword-search or bulk-list endpoint, only fetch-by-known-ID and a public SPARQL endpoint. The adapter searches via SPARQL (title and artist-name text matching) and hydrates each result over REST, same per-result cost model as the Met's per-object fan-out — never a full-collection crawl. Rights are genuinely two-tier: collection metadata (title, artist, date) is CC0 across the dataset, but each image is independently rights-checked against its own media entity, since Getty's Open Content Program covers roughly 91,000 of the museum's ~168,000 objects — the remainder have open metadata but a still-copyrighted image. Records in that remainder are accepted (not rejected) with imageOpenAccess: false and no imageUrls.full, matching how this project treats every genuinely two-tier source.
Suggest a museum
If you know an open-access collection that should be on this list and you can't write the adapter yourself, open a museum-source issue. The form asks for the API URL, the rights field, and a sample record. Anyone — me, or a future contributor — can pick it up from there and build the adapter.
The contribution that matters is the source knowledge. Knowing what's in a collection and how that museum represents rights is the part the code can't do for itself.
If you can write the adapter, see CONTRIBUTING.md.
Schema
Full TypeScript definitions in src/types.ts. The Artwork shape is stable; additional fields may be added but existing fields will not be repurposed.
Highlights:
displayDate(string, museum-provided) preserved alongside parsedyearStart/yearEnd(signed integers, BCE encoded as negatives).regionandperiodnormalized across museums (china,japan,tang dynasty, etc.).artist.attributionTypedistinguishesnamed/anonymous/workshop/after/attributed/circle/follower.imageOpenAccessis held distinct frommetadataOpenAccessbecause museums frequently publish open metadata for objects whose images are not openly licensed.
Compatibility
Artwork field semantics are stable. New versions may add fields or tools, but won't repurpose or remove existing ones within a major version.
Backward-compatible. New server versions may add fields to
Artwork, add new tools, or add new optional arguments. A v0.5 client calling a v0.6 server will continue to work; it just ignores fields it doesn't know.Forward-compatible. A v0.6 client calling an older v0.5 server will get records that lack v0.6-only fields, but the records it does get will validate against the older client's schema.
SemVer. While in v0.x, MINOR bumps may include backward-incompatible changes (per the SemVer spec for pre-1.0 versions). From v1.0 onwards, only MAJOR bumps may break compatibility.
Non-goals
Not a full art-history ontology. The dynasty and region tables cover the most-encountered cases; they are not exhaustive iconographic taxonomies.
Not a generic museum API client. The server only returns records that pass rights verification. If you need raw, unfiltered API access, talk to the museum APIs directly.
Not a rights advisor. The verification model establishes machine-checkable acceptance rules; final rights decisions in commercial or sensitive contexts remain the user's responsibility.
Not a content host. Image URLs point at each museum's CDN; this server does not rehost media.
Roadmap
v0.1: Met adapter, dynasty-aware date parser, license gate,
citetool, MCP resources.v0.2: Cleveland and AIC adapters,
discover_randomwith constraints,list_traditions.v0.3: Wikimedia Commons adapter (per-record rights model; covers works whose home museums lack public APIs).
v0.4: Europeana adapter (federated European institutions, opt-in via API key);
year_min/year_maxdate-range filter onsearch_artworks.v0.5:
.mcpbDesktop Extension bundle (one-click Claude Desktop install); migration to Node 22+node:sqlite(no native compile required). (here)v0.7: Wikidata enrichment (artist QIDs, movement, country, dedup across cache).
v0.8: Dominant-colour extraction across museums (
color: "#3a5f7d"discovery viasharp).v1.0: Artist-obscurity scoring (
object_count_total,museum_count) for deliberate exploration of less-canonical work.v2.0: Smithsonian, Rijksmuseum direct integration, Walters Art Museum, more European institutions.
Release cadence
This is a side project. New releases ship when one of three things happens: my own work needs a feature, a new museum is wired in, or a contributor's PR is merged. There is no fixed cadence. I do commit to reviewing and merging contributor PRs promptly.
Project status
This is actively maintained as of the latest release. Because it is a side project, if active maintenance ever stops I will archive the repository and say so here, rather than leave it looking live. The published npm package, the adapters, and the Artwork schema remain usable either way, and the code is MIT-licensed, so anyone is free to fork and continue it. Governance and the path for new maintainers are described in GOVERNANCE.md.
Changelog
Releases lists what shipped in each version, with notes.
Help maintain this
open-museum-mcp is an independently maintained side project, and it now carries two things that benefit from more hands:
The MCP engine — the museum adapters, the rights gate, the date parser, the federation core. New collections, rights-model corrections, and bug reports are all welcome; CONTRIBUTING.md is the starting point.
The openclearance Clearance Manifest spec (
spec/clearance/) — a portable, fail-closed rights-clearance format emitted by theclearance_recordtool. Schema review, conformance tests, and additional per-museum rule mappings are especially valuable while v0.1 is young and the schema can still absorb feedback.
If you'd like to help — code, review, documentation, or rights expertise — open an issue or a PR. And if your organisation relies on this and would like to fund its ongoing maintenance, open an issue or get in touch; a sponsorship path is being set up.
Contributing a museum adapter
See CONTRIBUTING.md. The short version:
Implement the
Fetcherinterface insrc/fetchers/{code}.ts.Add a
validate{Code}Licensefunction insrc/licenseGate.tswith explicit accept rules and strict default deny.Add region/period mappings to
src/data/regions.jsonandsrc/data/dynasties.jsonif the new collection introduces unmapped traditions.Add fixture-based tests in
tests/{code}.test.tscovering: one accepted record, one rejected (non-open) record, one rejected (missing field) record.Register the adapter in
src/server.ts.
The license gate is the most opinionated part of the codebase. Additions should err strict.
Security
npm auditclean at launch. Zero vulnerabilities at any severity level across runtime and dev dependencies as of v0.1.stdio-only transport. No HTTP listener, no auth surface to bypass. The server only speaks to the MCP client over standard streams.
Strict input validation. All tool arguments pass through Zod schemas; artwork IDs are constrained to
/^[a-z]+:[1-9]\d*$/. The resource URI handler re-validates the constructed ID against the same regex, so URI-form requests can't bypass the constraint.Defense-in-depth on rights. The Met search filter
isPublicDomain=trueis sometimes inconsistent with the per-object boolean. The license gate runs again on every fetched record and rejects any disagreement.Parameterized SQL. All
better-sqlite3calls use named/positional parameters; zero string-concatenated SQL paths.No file writes from user input. The cache directory is created at
~/.open-museum-mcp/cache.db(or whereverOMM_CACHE_PATHpoints) with mode0o700and the cache file at0o600; no fetcher rehosts media bytes locally.
If you find a record the gate accepts that shouldn't pass, please open an issue with the artwork ID and the museum's raw API response. Rights correctness is the project's most important property, and the part where outside review most helps.
Disclaimer
This software validates open-access status against the rights metadata each museum publishes and the rules each museum requests. It cannot independently verify third-party rights, derived works, model release issues, or sensitive cultural-heritage considerations beyond what the source museum represents. Several museums (e.g. the Art Institute of Chicago) explicitly note that even CC0-marked images may carry obligations around third-party permissions or culturally sensitive material. Always confirm against the source museum's terms before commercial or sensitive use.
License
MIT. See LICENSE.
Available Tools
5 toolsciteA
Render a citation for an artwork. Styles: "full" (artist, title, date, museum, license, URL), "caption" (image caption form), "short" (inline reference).
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Normalized artwork ID. | |
| style | No | full |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must fully disclose behavioral traits. It only describes output styles but does not mention idempotency, side effects, authentication needs, or rate limits. For a read-like operation, this is a notable gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the main purpose, and every word adds value. No redundancy or unnecessary detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with two parameters and no output schema, the description covers the essential purpose and parameter variations. It omits details about the return format (e.g., plain text vs. JSON) but is otherwise complete for typical use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
While schema coverage is 50%, the description adds meaning to the 'style' parameter by explaining what each enum value produces ('full' includes artist, title, etc.; 'caption' for image captions; 'short' for inline references). The 'id' parameter is adequately described in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Render a citation for an artwork' and lists three distinct styles ('full', 'caption', 'short'), making the tool's purpose specific and differentiating it from sibling tools like 'discover_random' or 'search_artworks'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains each style's purpose ('full' includes all fields, 'caption' for image captions, 'short' for inline references), providing clear context for when to use each variant. However, it does not explicitly state when not to use this tool or alternative tools, though sibling tools are sufficiently different.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
discover_randomA
Pick one random artwork from the local cache that matches the given constraints. Useful for breaking out of repetitive search territory (e.g. surface a random Edo-period work to satisfy a no-back-to-back-European-pre-1900 pairing rule). On a cold cache with region or period constraints provided, auto-seeds via a small search_artworks call derived from those constraints before sampling — so first-time use works without manually warming the cache. Without constraints, returns a hint to run search_artworks first.
| Name | Required | Description | Default |
|---|---|---|---|
| museum | No | Optional museum code to restrict to (met, cleveland, aic). | |
| period | No | Normalized period tag (e.g. "tang dynasty", "edo", "safavid"). Exact match. | |
| region | No | Normalized region tag (e.g. "china", "japan", "netherlands"). Exact match. | |
| not_artist | No | Artist names to exclude (exact match against the canonical artist name field). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so description fully discloses caching behavior, auto-seeding on cold cache with region/period, and hint when no constraints. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is concise yet comprehensive, front-loaded with purpose followed by usage scenario and technical details. Every sentence contributes meaningfully.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists; description implies return of an artwork but doesn't detail format. However, it thoroughly covers parameters, caching, and constraints, making it sufficiently complete for a random-selection tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. Description adds value by explaining how parameters (region, period) trigger auto-seeding and notes exact matching for not_artist, going beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool picks a random artwork from a local cache matching constraints, differentiating it from search_artworks and other siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear when-to-use guidance (breaking repetitive search), includes a concrete example scenario, and explains behavior with and without constraints, suggesting alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_artworkA
Fetch a single artwork by its normalized ID (e.g. met:436533).
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Normalized artwork ID, format museumcode:numericid |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, description states read-only fetch but does not disclose error behavior or rate limits; adequate for simple fetch.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, no redundancy, efficiently conveys essence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given simple 1-param tool, description explains input but omits return value details; acceptable for its simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema already covers parameter; description adds format details and example, enhancing clarity beyond schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly specifies action (fetch), resource (single artwork), and mechanism (by normalized ID). Distinct from siblings: search_artworks returns multiple, others are different in scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides format example, implicitly conveys use case (have an ID), but lacks explicit when-to-use vs alternatives like search_artworks.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_traditionsA
List the regions and periods present in non-expired cached records, with per-museum record counts. Helps you see which traditions are well-represented before searching, and where holdings are sparse. Returns { regions, periods } where each entry has { tag, label, coverage: { museumCode: count } }. On an empty cache, returns a hint to run search_artworks first — list_traditions is a meta-tool over what you have already collected, not a search trigger.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided; description fully discloses behavior: lists from non-expired cached records, returns hint on empty cache, specifies return structure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise, front-loaded sentences, each adding essential information without wordiness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters and no output schema, description covers purpose, usage, return shape, and edge case (empty cache) comprehensively.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters in schema, so baseline is 4. Description adds no parameter info, which is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states it lists regions and periods from cached records with counts, distinguishing it from siblings like search_artworks by noting it's a meta-tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to run search_artworks first if cache is empty, and clarifies it's not a search trigger, providing clear when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_artworksA
Search across registered open-access museum collections. Returns artwork records that pass source-specific rights verification (ambiguous records excluded by default). Supports an optional date-range filter for researcher queries like "Dutch genre painting 1640–1680".
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | Free-text query. | |
| museum | No | Optional museum code. Currently registered: met, cleveland, aic, wikimedia (Commons), europeana (federated European institutions; requires EUROPEANA_API_KEY env var). | |
| year_max | No | Optional inclusive upper bound on artwork creation year. Negative for BCE. Records with no parseable date are excluded when any year bound is set. | |
| year_min | No | Optional inclusive lower bound on artwork creation year. Negative for BCE (e.g. -500 = 500 BCE). Records with no parseable date are excluded when any year bound is set. | |
| has_image | No | Restrict to records with an image URL. Defaults to true. Note: some museums (e.g. The Met) only expose images-only search server-side. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It discloses that ambiguous records are excluded by default, that rights verification is applied, and that records with no parseable date are excluded when year bounds are set. The parameter description for has_image also notes museum-specific behavior (Met only exposes images-only search server-side). This is good but could mention authentication or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with two sentences front-loading the main purpose and then adding a usage example. No unnecessary words or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 6 parameters and no output schema, the description covers core functionality and filtering but lacks details on return format, pagination, or ordering. It is adequate but not fully complete for a search tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is high (83%), so baseline is 3. The description adds value by giving a specific date-range usage example ('Dutch genre painting 1640–1680') that illustrates the year_min and year_max parameters. It also provides context about rights verification, though not directly per parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool searches across registered open-access museum collections and returns artwork records with rights verification. It uses specific verb and resource, distinguishing it from siblings like get_artwork (retrieval by ID) and discover_random (random selection).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a concrete example of when to use the date-range filter ('researcher queries like Dutch genre painting 1640–1680'), which helps with usage context. However, it does not explicitly state when not to use this tool or contrast it with sibling tools.
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.
5 tool updates
v0.1.0- First observed
cite - First observed
discover_random - First observed
get_artwork - First observed
list_traditions - First observed
search_artworks
TDQS
Scored across 5 tools
Each tool has a distinct, non-overlapping purpose: cite for citations, discover_random for random selection, get_artwork for specific artwork retrieval, list_traditions for metadata exploration, and search_artworks for querying. No ambiguity.
All tool names follow a consistent verb_noun pattern in lowercase snake_case (e.g., search_artworks, list_traditions), with 'cite' being a concise verb that fits the pattern. Highly predictable and readable.
With 5 tools covering search, retrieval, citation, random discovery, and metadata listing, the set is well-scoped for a museum API. Each tool earns its place without redundancy.
The tool set covers all essential operations for a read-only museum data API: searching, fetching single items, citing, random discovery, and exploring available traditions. No obvious gaps given the domain.
Maintenance
Related MCP Connectors
Cleveland Museum of Art Open Access API (~63k artworks, many CC0)
Search 14.5M Smithsonian Open Access objects, get CC0 images, find cross-collection connections.
MET Museum collection via MCP — 500K+ artworks, metadata, provenance, open-access images.
Art MCP — Metropolitan Museum of Art Collection API (free, no auth)
Related MCP Servers
- AlicenseAqualityBmaintenanceA MCP Server that lets user ask AI models to discover the collection of the Metropolitan Museum of Art. Adds the discovered art works as Resources on the server.4212 npm35MIT
- AlicenseAqualityAmaintenanceLicense-first federated image search for AI agents and humans. Exposes MCP tools for concise, attribution-aware image discovery, license probing, and guarded downloads across open, platform, and editorial sources.749 npm3MIT
- AlicenseNot gradedqualityCmaintenanceEnables querying the Cleveland Museum of Art's open access API to search artworks by filters like type, artist, and CC0 status, retrieve details by accession number, find creators, and explore exhibitions.6 npm1MIT
- AlicenseAqualityDmaintenanceMCP server for searching museum collections and viewing artwork images and metadata from multiple museums, including the Met, Art Institute of Chicago, Rijksmuseum, and more.248 npm2MIT