Connects Claude to the Metropolitan Museum of Art's public collection API with three focused tools: list all 19 curatorial departments, search 500K+ artworks by keyword with filters for date range, medium, geography, and public domain status, and fetch full object records including provenance, artist bios, Getty and Wikidata links, and CC0 image URLs. Built on the Met's open API, so no authentication required. Handles batch fetching for up to 20 objects at once with partial failure reporting, and surfaces CC0 flags so you know which images are actually usable. Reach for this when you need structured art historical data, open access images for display, or want to let Claude search museum collections with precise filtering rather than keyword scraping.
claude mcp add --transport http met-museum https://met-museum.caseyjhand.com/mcpRun in your terminal. Add --scope user to make it available in every project.
Review the command, arguments, and environment values before installing — MCP servers run with your local permissions.
Verified live against the running server on Jun 10, 2026.
met_list_departmentsReturn the 19 curatorial departments at The Metropolitan Museum of Art with their numeric IDs and display names. Use before calling met_search_collections to discover valid departmentId values. The department list is fetched live on each call to remain accurate if the Met reor...Return the 19 curatorial departments at The Metropolitan Museum of Art with their numeric IDs and display names. Use before calling met_search_collections to discover valid departmentId values. The department list is fetched live on each call to remain accurate if the Met reor...
No parameters — call it with no arguments.
met_search_collectionsSearch the Metropolitan Museum of Art collection by keyword and optional filters; returns total match count and a page of object IDs. Always chain the returned IDs to met_get_object (up to 20 at a time) to retrieve full records. Search relevance is keyword-based, not semantic...11 paramsSearch the Metropolitan Museum of Art collection by keyword and optional filters; returns total match count and a page of object IDs. Always chain the returned IDs to met_get_object (up to 20 at a time) to retrieve full records. Search relevance is keyword-based, not semantic...
q*stringlimitintegermediumstringdateEndintegerisOnViewbooleandateBeginintegerhasImagesbooleangeoLocationarrayisHighlightbooleandepartmentIdintegerisPublicDomainbooleanmet_get_objectFetch full records for one or more Met Museum object IDs. Accepts up to 20 IDs per call, fetches in parallel (concurrency-limited), and returns partial-success — a single 404 does not fail the whole batch. Object IDs come from met_search_collections. Non-public-domain objects...1 paramsFetch full records for one or more Met Museum object IDs. Accepts up to 20 IDs per call, fetches in parallel (concurrency-limited), and returns partial-success — a single 404 does not fail the whole batch. Object IDs come from met_search_collections. Non-public-domain objects...
objectIDs*arraySearch the Metropolitan Museum of Art collection, fetch full artwork records and open-access images via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://met-museum.caseyjhand.com/mcp
Three tools for browsing and fetching Metropolitan Museum of Art collection data:
| Tool | Description |
|---|---|
met_list_departments | Return all 19 curatorial departments with their numeric IDs and display names |
met_search_collections | Search the collection by keyword with filters for department, date range, medium, geography, on-view status, public-domain status, and highlight designation |
met_get_object | Fetch full records for one or more object IDs — metadata, provenance, artist info, CC0 image URLs, tags, and Wikidata links |
met_list_departmentsReturn the 19 curatorial departments at The Metropolitan Museum of Art with their numeric IDs and display names.
met_search_collections to discover valid departmentId valuesmet_search_collectionsSearch the Met collection by keyword and optional filters.
met_list_departments to get valid IDs)"Paintings", "Sculptures", "Ceramics") — maps to the classification field, not material descriptionsisPublicDomain=true restricts to CC0 open-access objects (guaranteed usable image URLs)hasImages=true includes any object with images (includes copyrighted works without reusable URLs)isHighlight=true restricts to collection highlights designated by the MetisOnView=true restricts to objects currently on display in a Met gallerylimit object IDs (default 20, max 500)met_get_object in batches of up to 20met_get_objectFetch full records for one or more Met Museum object IDs.
Built on @cyanheads/mcp-ts-core:
none, jwt, oauthin-memory, filesystem, Supabase, Cloudflare KV/R2/D1Metropolitan Museum of Art collection:
met_get_objectAgent-friendly output:
isPublicDomain and hasCC0Image flags distinguish CC0 objects from works with inaccessible images, so agents can reason about what they can actually displaymet_get_object returns objects and failed arrays so callers receive successful records alongside structured per-ID error contextmet_search_collections returns total, returned, and truncated fields so agents know when to refine filters or increase limitA public instance is available at https://met-museum.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"met-museum-mcp-server": {
"type": "streamable-http",
"url": "https://met-museum.caseyjhand.com/mcp"
}
}
}
Add the following to your MCP client configuration file.
{
"mcpServers": {
"met-museum-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/met-museum-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"met-museum-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/met-museum-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"met-museum-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/met-museum-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
git clone https://github.com/cyanheads/met-museum-mcp-server.git
cd met-museum-mcp-server
bun install
cp .env.example .env
# edit .env as needed (all vars are optional)
All configuration is validated at startup via Zod schemas in src/config/server-config.ts.
| Variable | Description | Default |
|---|---|---|
MCP_TRANSPORT_TYPE | Transport: stdio or http | stdio |
MCP_HTTP_PORT | HTTP server port | 3010 |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth | none |
MCP_LOG_LEVEL | Log level (debug, info, warning, error) | info |
LOGS_DIR | Directory for log files (Node.js only) | <project-root>/logs |
OTEL_ENABLED | Enable OpenTelemetry instrumentation | false |
MET_BASE_URL | Met Collection API base URL (override for local stubs) | https://collectionapi.metmuseum.org/public/collection/v1 |
MET_REQUEST_TIMEOUT_MS | Per-request HTTP timeout in milliseconds | 10000 |
MET_BATCH_CONCURRENCY | Max parallel fetches in met_get_object | 5 |
See .env.example for the full list of optional overrides.
Build and run:
# One-time build
bun run rebuild
# Run the built server
bun run start:stdio
# or
bun run start:http
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security
bun run test # Vitest test suite
bun run lint:mcp # Validate MCP definitions against spec
docker build -t met-museum-mcp-server .
docker run --rm -p 3010:3010 met-museum-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/met-museum-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools and inits the Met service. |
src/config | Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools | Tool definitions (*.tool.ts) — met_list_departments, met_search_collections, met_get_object. |
src/services/met | Met Collection API client — HTTP, request timeout, response normalization. |
tests/ | Unit and integration tests mirroring src/. |
See CLAUDE.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storagecreateApp() in src/index.tsIssues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Data from The Metropolitan Museum of Art Collection API (CC0).
Apache-2.0 — see LICENSE for details.
MCP_LOG_LEVELdefault: infoSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
MCP_HTTP_HOSTdefault: 127.0.0.1The hostname for the HTTP server.
MCP_HTTP_PORTdefault: 3010The port to run the HTTP server on.
MCP_HTTP_ENDPOINT_PATHdefault: /mcpThe endpoint path for the MCP server.
MCP_AUTH_MODEdefault: noneAuthentication mode to use: 'none', 'jwt', or 'oauth'.