Staedel Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Staedel Mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
<p align="center"> <img src="assets/staedel-museum.webp" alt="Städel Museum, Frankfurt am Main" width="640" /> </p>
A Model Context Protocol server that gives AI assistants direct access to the [Städel Museum](https://www.staedelmuseum.de) Digital Collection. It talks to the museum's public OAI-PMH interface (LIDO metadata format), so an assistant can harvest object records, read rich multilingual metadata, and display high-resolution artwork images — with an interactive browsing UI (MCP Apps) on top.
This is a personal portfolio project built to demonstrate working with the Model Context Protocol, an OAI-PMH/LIDO harvesting API, and MCP Apps interactive UIs end-to-end — not an official Städel Museum product.
| Tool | Description |
|---|---|
list-sets | Lists the OAI-PMH sets (e.g. Masterpieces, Prints and Drawings) available to filter by. |
search-museum-objects | Harvests the identifiers of live (non-deleted) objects, filtered by set and/or a from/until date range, with pagination via resumptionToken. |
get-museum-object | Resolves one object's full LIDO record into clean, normalized JSON — titles, artists, date, medium, dimensions, image, license — plus the image itself. |
open-staedel-explorer | Opens an interactive MCP App UI for browsing and filtering the collection visually, in hosts that support it. |
Because the Städel exposes its collection through OAI-PMH (a harvesting protocol, not a search engine), there is no full-text keyword search — you filter by set and/or date range, then fetch full details per object. The tool descriptions make this explicit so the assistant doesn't assume Google-style search is available.
<p align="center"> <img src="assets/mcp-inspector-tools.png" alt="Tools listed in the MCP Inspector" width="800" /> </p>
src/
├── index.ts # entry point: stdio, or stateless Streamable HTTP with --http
├── server.ts # the four tools and the explorer UI resource
├── api.ts # OAI-PMH client: throttled fetch, retry, XML parsing
├── lido.ts # flattens a LIDO record into the normalized object (and its Zod schema)
└── explorer.ts # the self-contained MCP App HTML for the explorerlido.ts does the interesting work: LIDO is a verbose, multilingual, deeply nested XML format, and flattenLido turns it into a small, stable JSON shape — resolving xml:lang variants (preferring English, falling back to German), picking the largest image rendition, and reading each object's actual rights statement instead of assuming one blanket license.
carry a different rights statement (e.g. Public Domain Mark) — get-museum-object reports the actual license for each object rather than hard-coding one.
credit line reported in the license field.
git clone https://github.com/topoftheblock/staedel-mcp.git
cd staedel-mcp
corepack enable
pnpm install
pnpm run buildStdio (used by Claude Desktop, Claude Code, and most MCP clients):
node dist/index.jsStreamable HTTP (for testing with clients that connect over HTTP):
node dist/index.js --http
# -> http://localhost:3001/mcp (localhost only; override the port with the PORT env var)Add to your MCP client's config (e.g. claude_desktop_config.json):
{
"mcpServers": {
"staedel-museum": {
"command": "node",
"args": ["/absolute/path/to/staedel-mcp/dist/index.js"]
}
}
}npx @modelcontextprotocol/inspector node dist/index.js<p align="center"> <img src="assets/mcp-inspector-list-sets-result.png" alt="list-sets tool result in the MCP Inspector" width="800" /> </p>
pnpm run watch # tsc --watch
pnpm run check # type-check without emitting| Environment variable | Default | Purpose |
|---|---|---|
STAEDEL_API_TIMEOUT_MS | 10000 | Per-request timeout to the Städel API. |
PORT | 3001 | Port for --http mode. |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.