
Met Museum Mcp Server
io.github.cyanheadsv0.8.0更新於 Oct 8, 2026
Search the Met collection, browse by department or update date, fetch full records and CC0 images.
概覽
讓助理搜尋大都會藝術博物館藏品、依部門或更新日期瀏覽,並取得完整藝術品記錄與 CC0 圖片。
- 功能
- 四個工具包裝 Met 的公開 Collection API。met_list_departments 回傳全部 19 個策展部門與數字 ID;met_search_collections 依關鍵字搜尋,並可依部門、年代範圍、材質、地理、是否有圖片、是否展出與是否為重點展品篩選;met_list_objects 依部門或更新日期列出物件 ID;met_get_object 取得 1-20 個 ID 的完整記錄,包含中繼資料、來源、藝術家資訊、標籤、Wikidata 連結,並可選擇回傳最多 3 張 CC0 圖片作為影像內容。結果會回報總數、分頁、截斷情況與逐 ID 失敗資訊。
- 適用情境
- 當助理需要藝術史或博物館藏品資訊時適用:依關鍵字、材質、年代或部門尋找作品,核對來源與藝術家歸屬,或取得可公開展示的公有領域圖片。適合針對 Met 開放藏品的研究、目錄瀏覽與資料補充工作,而非一般網頁搜尋。公開託管端點方便免安裝快速試用。
- 執行需求
- 可使用公開託管的 Streamable HTTP 端點(免安裝),或在本機執行:Bun v1.4.0+ 或 Node.js v24+,也可使用 Docker。可透過 npx、bunx 或已發佈的 npm 套件安裝。不需要 API 金鑰,Met Collection API 公開且無需驗證。選用環境變數包括 MCP_TRANSPORT_TYPE、MCP_HTTP_PORT、MCP_AUTH_MODE、MCP_LOG_LEVEL、MET_BASE_URL、MET_REQUEST_TIMEOUT_MS、MET_CALL_DEADLINE_MS 與 MET_BATCH_CONCURRENCY。需要連線至 Met API 的網路。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Met Museum Mcp Server,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。
其他 MCP 客戶端
把它新增到你客戶端的 mcpServers 設定中。
{
"mcpServers": {
"met-museum-mcp-server": {
"type": "http",
"url": "https://met-museum.caseyjhand.com/mcp"
}
}
}README
@cyanheads/met-museum-mcp-server
Search the Metropolitan Museum of Art collection, browse it by department or update date, fetch full artwork records and open-access images via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://met-museum.caseyjhand.com/mcp
Overview
The Metropolitan Museum of Art's public Collection API. Search the collection by keyword and filters, or browse it by department and update date, then fetch full object records — metadata, provenance, and CC0 open-access images — from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
Tools
Capability reference
met_list_departments tool
- No input; returns all 19 curatorial departments, each a numeric
departmentIdwith itsdisplayName(e.g., "Egyptian Art") departmentIdvalues are the valid input for thedepartmentIdfilter onmet_search_collectionsandmet_list_objects- Typed errors:
upstream_blocked,upstream_unavailable(the Met answered 500/502/503/504 through every retry), andretry_deadline_exceeded(the call's time budget ran out)
met_search_collections tool
- Keyword
q(required), matched across all text fields unlessmatchFieldnarrows it to"title"or"tags"."*"matches every object, for a search by filters alone; an accession number from a label ranks its object first. Plus filters:departmentId,medium(a case-sensitive classification as the Met spells it —"Paintings", not"Oil on canvas"),dateBegin/dateEnd(integer years, negative = BCE, set together), onegeoLocation,hasImages,isOnView, andisHighlight(trueonly) departmentId7 (The Cloisters) and 17 (Medieval Art) share one search result set at the Met: each page keeps only the requested department's IDs, whiletotaland paging count both, so a page can hold fewer thanlimitIDs; anoticesays so, andmet_list_objectsgives exact department membership- Up to 500 IDs per page (default 20), paged by
offset/nextOffsetthrough the first 10,000 matches only;totalstill reports the full count, with anoticewhen it exceeds 10,000 - Zero matches is a result, not an error:
total: 0with anoticesaying whether the keyword matches nothing or the filters removed every match, and which filters to correct or drop. Every result echoes the applied query aseffectiveQuery - Typed errors:
invalid_date_range,invalid_filter(a blankq,medium, orgeoLocation),invalid_department,upstream_blocked,upstream_unavailable,retry_deadline_exceeded
met_list_objects tool
- Filters
departmentId(frommet_list_departments) andupdatedSince(YYYY-MM-DD— records created or revised on or after that day), alone or together; with neither, the whole collection (over 500,000 IDs). Up to 500 IDs per page (default 20), in ascending order, paged byoffset/nextOffsetwith no depth limit - Typed errors:
invalid_department,invalid_date(an impossible date such as2026-02-30),upstream_blocked,upstream_unavailable,retry_deadline_exceeded; an empty list is a result, not an error, with anoticenaming the filters, and every result echoes the applied filters aseffectiveQuery - Each list is cached for up to an hour, so a record revised within the last hour may not appear yet
met_get_object tool
- 1–20 IDs per call, from
met_search_collectionsormet_list_objects; a repeated ID is fetched and returned once - Partial success: per-ID errors land in
failed[], and the call fails only when every ID does —all_not_foundwhen every ID was a 404,upstream_blockedwhen the Met's firewall refused a request,retry_deadline_exceededwhen every fetch ran out of the call's time budget,upstream_unavailablewhen a fetch met a Met API outage, andall_failedotherwise; records past a 60,000-bytestructuredContentbudget are listed indeferred[]with their sizes, to re-request isPublicDomain/hasCC0Imagegate image URLs — non-public-domain objects return emptyprimaryImage,primaryImageSmall, andadditionalImages; sparse fields are empty or null, never fabricatedincludeImages: trueattaches the CC0 web-display image (about 600 px on the long edge) of the first 3 returned records that have one, as image content after a caption naming the object, andimages[]gives each returned record's outcome (attached,no_cc0_image,over_cap,unavailable). The bytes ridecontent[]only, so a client that passes the model onlystructuredContentwon't show them- The Artist line carries the full attribution and role —
artistPrefix("Style of"), the name,artistSuffix, andartistRole("Patron") — so a follower's work or a patron never reads as the named artist's own;rightsAndReproductionnames the rights holder on the copyrighted works that carry one, besideaccessionYear metadataDateis the record's last revision, the timestampmet_list_objectsupdatedSincecompares;departmentIdresolves the record's department name (five differ frommet_list_departments) to the IDmet_list_objectsandmet_search_collectionstake, ornullwhen the name is not recognized- The search index can list IDs the object endpoint no longer serves, so a 404's guidance is to drop the ID rather than search for it again
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Met Museum-specific:
- 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
- A 403 from the Met's firewall surfaces on every tool as
upstream_blocked, non-retryable: the block covers the server's address for minutes, so the recovery is to wait and send fewer requests - A 500, 502, 503, or 504 that outlasts the retries surfaces on every tool as
upstream_unavailable; once every fetch in flight has failed without the Met answering any ID,met_get_objectstops requesting the rest of the batch, so a 5xx outage costs at mostMET_BATCH_CONCURRENCY× 4 requests (20 at the default) however many IDs were asked for - No error carries the Met's HTML or JSON error page — an HTTP failure reaches the caller as its code, message, and status, or, inside a
met_get_objectbatch, as that ID'sfailed[]message
Agent-friendly output:
- Provenance on every record —
isPublicDomainandhasCC0Imageflags distinguish CC0 objects from works with inaccessible images, so agents can reason about what they can actually display - Partial failure reporting —
met_get_objectreturnsobjectsandfailedarrays so callers receive successful records alongside structured per-ID error context - Truncation signaling —
met_search_collectionsandmet_list_objectsreturntotal,returned,truncated,remaining,nextOffset, and the resolvedoffset; the text marks each page(truncated),(complete), or(offset beyond result set), and search adds(window end)for a page that stops at its 10,000-match window short oftotal - Byte-budget disclosure —
met_get_objectreportsdeferred[]records with their sizes when a batch exceeds its serialized-response budget, so callers can size a follow-up call precisely
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:
Self-Hosted / Local
Add the following to your MCP client configuration file.
Or with npx (no Bun required):
Or with Docker:
For Streamable HTTP, set the transport and start the server:
Prerequisites
- Bun v1.4.0 or higher (or Node.js v24+).
- No API key required — the Met Collection API is public and unauthenticated.
Installation
- Clone the repository:
- Navigate into the directory:
- Install dependencies:
- Configure environment:
Configuration
All configuration is validated at startup via Zod schemas in src/config/server-config.ts.
See .env.example for the full list of optional overrides.
Running the server
Local development
-
Build and run:
-
Run checks and tests:
Docker
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
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storage - Register new tools via the arrays in
createApp()insrc/index.ts - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
Data attribution
Data from The Metropolitan Museum of Art Collection API (CC0).
License
Apache-2.0 — see LICENSE for details.
來源:README.md,提交 01be3e5
工具
0版本歷史
5- v0.8.0最新Oct 4, 2026
- v0.7.0Sep 30, 2026
- v0.6.0Sep 25, 2026
- v0.5.3Sep 19, 2026
- v0.5.2Sep 16, 2026
