Skip to main content
Glama
cyanheads

@cyanheads/met-museum-mcp-server

by cyanheads

Version License Docker MCP Server npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework

Public Hosted Server: https://met-museum.caseyjhand.com/mcp


Tools

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_departments

Return the 19 curatorial departments at The Metropolitan Museum of Art with their numeric IDs and display names.

  • departmentId values are the valid inputs for the met_search_collections department filter


met_search_collections

Search the Met collection by keyword and optional filters.

  • Keyword search across title, artist name, culture, medium, tags, and other text fields

  • Filter by department ID (valid IDs from met_list_departments)

  • Filter by date range (integer years, negative = BCE)

  • Filter by medium/classification (e.g., "Paintings", "Sculptures", "Ceramics") — maps to the classification field, not material descriptions

  • Filter by geographic origin — country, region, or city; multiple values are AND-combined

  • isPublicDomain=true selects CC0 open-access objects — confirm CC0 status per object from met_get_object

  • Every filter draws on a partial upstream index: a filtered search omits some objects whose own record satisfies the filter, so absence from the results is not evidence about an object. Drop the filter to widen

  • A filtered search returns only objects that match the keyword. The Met index answers any filter with a fixed set of unrelated objects alongside the real matches, so the server runs the query a second time with no filters and returns the intersection; total counts that intersection. The two runs go out in parallel

  • That second run is best-effort. A keyword broad enough to time out on its own (q=the alone is 2.7 MB) returns the filtered results unchecked rather than failing the call, with a notice on the response saying they were not verified against the keyword — narrow the keyword to let the check run

  • hasImages=true includes any object with images (includes copyrighted works without reusable URLs)

  • isHighlight=true restricts to collection highlights designated by the Met

  • isPublicDomain and isHighlight accept true only. The upstream index is unsound on the false arm — it returns objects whose own record contradicts the filter — so false is rejected; omit the filter instead. hasImages and isOnView are unaffected and remain plain booleans

  • isOnView=true restricts to objects currently on display in a Met gallery

  • Paginate past limit with offset (default 0) — a broad query carries the same timeout risk on every page as on the first; narrow it with filters if paging times out

  • Returns total match count, truncation indicator, remaining count, nextOffset for the next page (null once exhausted), the resolved offset this page was read from, and up to limit object IDs (default 20, max 500)

  • Returned IDs resolve to full records via met_get_object (up to 20 per call)


met_get_object

Fetch full records for one or more Met Museum object IDs.

  • Accepts 1–20 IDs per call; a repeated ID is fetched and returned once, at its first position

  • Partial-success — a single 404 does not fail the whole batch; failed IDs are reported per-ID

  • Full metadata: title, department, classification, medium, dimensions, date, culture, period, dynasty, accession number, credit line, gallery number

  • Artist data: display name, biography, nationality, dates, Getty ULAN URL, Wikidata URL

  • Constituents array for all associated persons (null for anonymous/unattributed works)

  • Controlled vocabulary tags with Getty AAT and Wikidata URLs

  • Nested geography block with the nine findspot fields beyond country/regiongeographyType, city, state, county, subregion, locale, locus, excavation, river — each an empty string when the Met records nothing

  • Structured measurements array: one entry per measured element, each with an open map of axis name to value (centimeters for spatial axes, kilograms for weight). Null when the Met records none

  • Records are returned whole and never truncated. A call whose records together exceed a cumulative budget on serialized structuredContent bytes returns fewer of them; the rest are listed in deferred[] with their sizes, to re-request in a follow-up call. content[] re-renders the admitted records, so the delivered response is roughly twice the budget

  • Canonical metmuseum.org URL for human follow-up

  • CC0 objects return full-resolution and web-display image URLs plus additional image arrays

  • Object-level Wikidata URL for enrichment via external knowledge graph tools

Related MCP server: open-museum-mcp

Features

Built on @cyanheads/mcp-ts-core:

  • Declarative tool definitions — single file per tool, framework handles registration and validation

  • Unified error handling — handlers throw, framework catches, classifies, and formats

  • Pluggable auth: none, jwt, oauth

  • Swappable storage backends: in-memory, filesystem, Supabase, Cloudflare KV/R2/D1

  • Structured logging with optional OpenTelemetry tracing

  • STDIO and Streamable HTTP transports

Metropolitan Museum of Art collection:

  • 500K+ artworks spanning 5,000 years from the Met's public collection API

  • CC0 open-access data from The Metropolitan Museum of Art — free to use without permission or attribution

  • Parallel batch fetching with configurable concurrency for met_get_object

  • Linked data on every object — Getty ULAN and AAT URLs, Wikidata entity URLs for artists, tags, and works

Agent-friendly output:

  • Provenance on every record — isPublicDomain and hasCC0Image flags distinguish CC0 objects from works with inaccessible images, so agents can reason about what they can actually display

  • Partial failure reporting — met_get_object returns objects and failed arrays so callers receive successful records alongside structured per-ID error context

  • Truncation signaling — met_search_collections returns total, returned, truncated, remaining, nextOffset, and the resolved offset fields so agents know when to refine filters, increase limit, or page further with offset; offset >= total marks a page that is empty because the offset ran past the end rather than because the query is exhausted

Getting started

Public Hosted Instance

A 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"
    }
  }
}

Self-Hosted / Local

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

Prerequisites

  • Bun v1.3.0 or higher (or Node.js v24+).

  • No API key required — the Met Collection API is public and unauthenticated.

Installation

  1. Clone the repository:

git clone https://github.com/cyanheads/met-museum-mcp-server.git
  1. Navigate into the directory:

cd met-museum-mcp-server
  1. Install dependencies:

bun install
  1. Configure environment:

cp .env.example .env
# edit .env as needed (all vars are optional)

Configuration

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_SESSION_MODE

HTTP session mode: auto, stateful, or stateless. This server explicitly sets stateless; the framework schema default is auto.

stateless

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.

Running the server

Local development

  • Build and run:

    # One-time build
    bun run rebuild
    
    # Run the built server
    bun run start:stdio
    # or
    bun run start: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

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.

Project structure

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/.

Development guide

See CLAUDE.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic

  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage

  • Register new tools via the arrays in createApp() in src/index.ts

  • Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields

Contributing

Issues 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).

License

Apache-2.0 — see LICENSE for details.

Maintenance

ActivityMaintained
ResponsivenessSlow

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    A 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.
    4
    266
    34
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Federated, license-verified search across open-access museum collections — currently The Met, Cleveland, AIC, Wikimedia Commons, and Europeana, with more being added. Strict-default-deny rights gate accepts only CC0 / Public Domain Mark, returning reuse-safe artwork with citations in three styles.
    5
    51
    11
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Search artists, releases, recordings, works, and labels; traverse relationships; resolve ISRC/ISWC/barcode; fetch cover art via MCP. STDIO or Streamable HTTP.
    35
    1
    Apache 2.0
  • 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.
    4
    26
    2
    MIT