open-museum-mcp 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # open-museum-mcp
2
2
 
3
+ [![CI](https://github.com/cfpramod/open-museum-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/cfpramod/open-museum-mcp/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/open-museum-mcp.svg)](https://www.npmjs.com/package/open-museum-mcp)
5
+
3
6
  > Open-access museum search for MCP clients, with rights verification per museum.
4
7
 
5
8
  ## Why I built this
@@ -10,7 +13,7 @@ If anyone else is exploring open-access art, I hope this helps. The plan is to k
10
13
 
11
14
  ## What you get
12
15
 
13
- - **One interface, registered museums.** The Met is live. Cleveland and the Art Institute of Chicago are next.
16
+ - **One interface, registered museums.** The Met, Cleveland Museum of Art, and the Art Institute of Chicago are live. Smithsonian and Rijksmuseum are next.
14
17
  - **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".
15
18
  - **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.
16
19
  - **Listable resources and deterministic citations.** `museum://{code}/{id}` resources, three citation styles, structured JSON search results.
@@ -65,14 +68,31 @@ A search call returns license-verified results in one normalized shape:
65
68
 
66
69
  ## Install
67
70
 
71
+ The package is on npm. The simplest setup is to add it directly to your MCP client config; `npx` will fetch and run it on first launch:
72
+
73
+ ```json
74
+ {
75
+ "mcpServers": {
76
+ "open-museum": {
77
+ "command": "npx",
78
+ "args": ["-y", "open-museum-mcp"]
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ That's it. Restart your MCP client and the tools below become available.
85
+
86
+ ### From source (for contributors)
87
+
68
88
  ```bash
89
+ git clone https://github.com/cfpramod/open-museum-mcp
90
+ cd open-museum-mcp
69
91
  npm install
70
92
  npm run build
71
93
  ```
72
94
 
73
- ### Wire into Claude Code
74
-
75
- Add to your MCP config (`.mcp.json` in a project, or your user-level config):
95
+ Then point the MCP config at the built binary:
76
96
 
77
97
  ```json
78
98
  {
@@ -85,8 +105,6 @@ Add to your MCP config (`.mcp.json` in a project, or your user-level config):
85
105
  }
86
106
  ```
87
107
 
88
- After restarting your MCP client, the tools below become available.
89
-
90
108
  ## Tools
91
109
 
92
110
  | Tool | Description |
@@ -94,6 +112,8 @@ After restarting your MCP client, the tools below become available.
94
112
  | `search_artworks(query, museum?, has_image?, limit?)` | Search across registered museums. Returns only records that pass the rights gate. |
95
113
  | `get_artwork(id)` | Fetch a single artwork by its normalized ID (e.g. `met:436535`). |
96
114
  | `cite(id, style?)` | Render a citation. `style`: `full` (artist, title, date, museum, license, URL), `caption` (image attribution), `short` (inline). |
115
+ | `discover_random(region?, period?, not_artist?, museum?)` | 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. |
116
+ | `list_traditions()` | 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. |
97
117
 
98
118
  ### `cite` example outputs
99
119
 
@@ -140,10 +160,10 @@ Each accepted record carries:
140
160
 
141
161
  - `imageOpenAccess`: the artwork's image may be reused under the recorded license.
142
162
  - `metadataOpenAccess`: the artwork's catalog metadata may be reused (often broader than image rights).
143
- - `license.type`: normalized license tier (`CC0`, `PD`, `CC-BY`, …; v0.1 only emits `CC0`).
163
+ - `license.type`: normalized license tier (`CC0`, `PD`, `CC-BY`, …; currently only emits `CC0`).
144
164
  - `license.rawValue`: the museum's own field value, preserved.
145
165
  - `license.verificationSource`: the exact museum field that was checked (e.g. `met.isPublicDomain`).
146
- - `license.confidence`: `high` for unambiguous accepts (the only level v0.1 emits).
166
+ - `license.confidence`: `high` for unambiguous accepts (the only level emitted today).
147
167
  - `license.verifiedAt`: ISO timestamp of when this verification ran.
148
168
 
149
169
  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](#disclaimer).
@@ -153,11 +173,19 @@ This is what "rights-verified" means here: validated against published museum me
153
173
  | Museum | Code | Auth | Status |
154
174
  |---|---|---|---|
155
175
  | The Metropolitan Museum of Art | `met` | none | ✅ v0.1 |
156
- | Cleveland Museum of Art | `cleveland` | none | 🚧 next |
157
- | Art Institute of Chicago | `aic` | none | 🚧 next |
176
+ | Cleveland Museum of Art | `cleveland` | none | v0.2 |
177
+ | Art Institute of Chicago | `aic` | none | v0.2 |
158
178
  | Smithsonian Open Access | `si` | API key (free) | 📋 v2 |
159
179
  | Rijksmuseum | `rijks` | API key (free) | 📋 v2 |
160
180
 
181
+ ## Suggest a museum
182
+
183
+ 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](https://github.com/cfpramod/open-museum-mcp/issues/new?template=museum-source.yml). 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.
184
+
185
+ 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.
186
+
187
+ If you can write the adapter, see [CONTRIBUTING.md](CONTRIBUTING.md).
188
+
161
189
  ## Schema
162
190
 
163
191
  Full TypeScript definitions in [`src/types.ts`](src/types.ts). The `Artwork` shape is stable; additional fields may be added but existing fields will not be repurposed.
@@ -178,8 +206,8 @@ Highlights:
178
206
 
179
207
  ## Roadmap
180
208
 
181
- - v0.1: Met adapter, dynasty-aware date parser, license gate, `cite` tool, MCP resources. **(here)**
182
- - v0.2: Cleveland and AIC adapters, `discover_random` with constraints (`region`, `period`, `not_artist`), `list_traditions`.
209
+ - v0.1: Met adapter, dynasty-aware date parser, license gate, `cite` tool, MCP resources.
210
+ - v0.2: Cleveland and AIC adapters (shipped); `discover_random` with constraints (`region`, `period`, `not_artist`), `list_traditions` next. **(here)**
183
211
  - v0.5: Dominant-color extraction across museums (`color: "#3a5f7d"` discovery via `sharp`).
184
212
  - v1.0: Artist-obscurity scoring (`object_count_total`, `museum_count`) for deliberate exploration of less-canonical work.
185
213
  - v2.0: Smithsonian, Rijksmuseum, Wikimedia Commons (long-tail).
package/dist/db.d.ts CHANGED
@@ -1,7 +1,20 @@
1
- import type { Artwork } from './types.js';
1
+ import type { Artwork, Tradition } from './types.js';
2
2
  export interface CacheConfig {
3
3
  path: string;
4
4
  }
5
+ /**
6
+ * Constraints for {@link Cache.getRandomObject}. All fields are AND-combined.
7
+ * Region and period are exact matches against the normalized values stored
8
+ * by each fetcher; museum is the registered code (`met`, `cleveland`, …);
9
+ * notArtist is an exact-match exclusion list against the canonical
10
+ * `artist_name` column.
11
+ */
12
+ export interface DiscoverFilter {
13
+ region?: string;
14
+ period?: string;
15
+ notArtist?: string[];
16
+ museumCode?: string;
17
+ }
5
18
  /**
6
19
  * SQLite-backed cache for normalized artworks and search-result IDs.
7
20
  *
@@ -23,9 +36,41 @@ export declare class Cache {
23
36
  constructor(config: CacheConfig);
24
37
  private init;
25
38
  upsertObject(art: Artwork): void;
39
+ /**
40
+ * Pick one random non-expired artwork that matches the constraints, or
41
+ * null if nothing matches.
42
+ *
43
+ * The query operates over the local cache only — meaning what the user
44
+ * has already searched and pulled. This is intentional: discover_random
45
+ * is a forcing-function over your search history, not a federated
46
+ * sample of every museum's catalog. Callers should seed the cache via
47
+ * search_artworks first.
48
+ *
49
+ * Note on `ORDER BY RANDOM()`: SQLite scans the matching set, which is
50
+ * fine for caches under ~100k rows. The cache here is bounded by what
51
+ * the user actually fetches and the 90-day object TTL.
52
+ */
53
+ getRandomObject(filter: DiscoverFilter): Artwork | null;
26
54
  getObject(id: string): Artwork | null;
27
55
  putQuery(cacheKey: string, ids: string[]): void;
28
56
  getQuery(cacheKey: string): string[] | null;
57
+ /**
58
+ * List the regions and periods present in non-expired cached records,
59
+ * with per-museum coverage counts. Useful for the `list_traditions`
60
+ * tool — callers see which traditions are well-represented before
61
+ * searching, and where holdings are sparse.
62
+ *
63
+ * `label` is currently the title-cased tag; v1.0+ may swap in a curated
64
+ * lookup (e.g. "tang" → "Tang Dynasty (618–907)") if the tag set
65
+ * grows enough to warrant one.
66
+ */
67
+ listTraditions(): {
68
+ regions: Tradition[];
69
+ periods: Tradition[];
70
+ };
71
+ private objectsCutoff;
72
+ private queriesCutoff;
73
+ private aggregateByTag;
29
74
  pruneExpired(): {
30
75
  objects: number;
31
76
  queries: number;
package/dist/db.js CHANGED
@@ -4,6 +4,13 @@ import { dirname } from 'node:path';
4
4
  const OBJECT_TTL_DAYS = 90;
5
5
  const QUERY_TTL_DAYS = 14;
6
6
  const MS_PER_DAY = 24 * 60 * 60 * 1000;
7
+ // Title-cases the first letter of each whitespace/hyphen-bounded word in
8
+ // an ASCII tag. The tag set in regions.json and dynasties.json is currently
9
+ // ASCII-only; if a future tag introduces non-ASCII letters, switch to a
10
+ // Unicode-aware regex (`/u` flag + `\p{L}` property class).
11
+ function titleCase(s) {
12
+ return s.replace(/\b\w/g, (c) => c.toUpperCase());
13
+ }
7
14
  /**
8
15
  * SQLite-backed cache for normalized artworks and search-result IDs.
9
16
  *
@@ -127,6 +134,55 @@ export class Cache {
127
134
  cached_at: new Date().toISOString(),
128
135
  });
129
136
  }
137
+ /**
138
+ * Pick one random non-expired artwork that matches the constraints, or
139
+ * null if nothing matches.
140
+ *
141
+ * The query operates over the local cache only — meaning what the user
142
+ * has already searched and pulled. This is intentional: discover_random
143
+ * is a forcing-function over your search history, not a federated
144
+ * sample of every museum's catalog. Callers should seed the cache via
145
+ * search_artworks first.
146
+ *
147
+ * Note on `ORDER BY RANDOM()`: SQLite scans the matching set, which is
148
+ * fine for caches under ~100k rows. The cache here is bounded by what
149
+ * the user actually fetches and the 90-day object TTL.
150
+ */
151
+ getRandomObject(filter) {
152
+ const conditions = [];
153
+ const params = [];
154
+ if (filter.region) {
155
+ conditions.push('region = ?');
156
+ params.push(filter.region);
157
+ }
158
+ if (filter.period) {
159
+ conditions.push('period = ?');
160
+ params.push(filter.period);
161
+ }
162
+ if (filter.museumCode) {
163
+ conditions.push('museum_code = ?');
164
+ params.push(filter.museumCode);
165
+ }
166
+ if (filter.notArtist && filter.notArtist.length > 0) {
167
+ const placeholders = filter.notArtist.map(() => '?').join(',');
168
+ conditions.push(`artist_name NOT IN (${placeholders})`);
169
+ params.push(...filter.notArtist);
170
+ }
171
+ // TTL gate: defense in depth on top of pruneExpired() at construction.
172
+ conditions.push('cached_at > ?');
173
+ params.push(new Date(Date.now() - OBJECT_TTL_DAYS * MS_PER_DAY).toISOString());
174
+ const where = `WHERE ${conditions.join(' AND ')}`;
175
+ const sql = `SELECT full_record FROM objects ${where} ORDER BY RANDOM() LIMIT 1`;
176
+ const row = this.db.prepare(sql).get(...params);
177
+ if (!row)
178
+ return null;
179
+ try {
180
+ return JSON.parse(row.full_record);
181
+ }
182
+ catch {
183
+ return null;
184
+ }
185
+ }
130
186
  getObject(id) {
131
187
  const row = this.db.prepare(`SELECT full_record, cached_at FROM objects WHERE id = ?`).get(id);
132
188
  if (!row)
@@ -163,11 +219,62 @@ export class Cache {
163
219
  return null;
164
220
  }
165
221
  }
222
+ /**
223
+ * List the regions and periods present in non-expired cached records,
224
+ * with per-museum coverage counts. Useful for the `list_traditions`
225
+ * tool — callers see which traditions are well-represented before
226
+ * searching, and where holdings are sparse.
227
+ *
228
+ * `label` is currently the title-cased tag; v1.0+ may swap in a curated
229
+ * lookup (e.g. "tang" → "Tang Dynasty (618–907)") if the tag set
230
+ * grows enough to warrant one.
231
+ */
232
+ listTraditions() {
233
+ const cutoff = this.objectsCutoff();
234
+ return {
235
+ regions: this.aggregateByTag('region', cutoff),
236
+ periods: this.aggregateByTag('period', cutoff),
237
+ };
238
+ }
239
+ objectsCutoff() {
240
+ return new Date(Date.now() - OBJECT_TTL_DAYS * MS_PER_DAY).toISOString();
241
+ }
242
+ queriesCutoff() {
243
+ return new Date(Date.now() - QUERY_TTL_DAYS * MS_PER_DAY).toISOString();
244
+ }
245
+ // Two literal SQL strings instead of `${column}` interpolation, so the
246
+ // README §Security claim "zero string-concatenated SQL paths" stays
247
+ // verbatim true. The `LOWER()` case-fold is defense-in-depth: if a future
248
+ // fetcher forgets to lowercase a tag, the variants still aggregate under
249
+ // one entry. The `tag != ''` filter drops empty-string ghosts so they
250
+ // can't surface as "" entries in the output.
251
+ aggregateByTag(column, cutoff) {
252
+ const sql = column === 'region'
253
+ ? `SELECT LOWER(region) AS tag, museum_code, COUNT(*) AS cnt
254
+ FROM objects
255
+ WHERE region IS NOT NULL AND region != '' AND cached_at > ?
256
+ GROUP BY LOWER(region), museum_code`
257
+ : `SELECT LOWER(period) AS tag, museum_code, COUNT(*) AS cnt
258
+ FROM objects
259
+ WHERE period IS NOT NULL AND period != '' AND cached_at > ?
260
+ GROUP BY LOWER(period), museum_code`;
261
+ const rows = this.db.prepare(sql).all(cutoff);
262
+ const byTag = new Map();
263
+ for (const row of rows) {
264
+ // Object.create(null) prevents prototype pollution if a future
265
+ // museum_code value ever collides with a built-in property name
266
+ // (`__proto__`, `constructor`, `toString`).
267
+ const existing = byTag.get(row.tag) ?? Object.create(null);
268
+ existing[row.museum_code] = row.cnt;
269
+ byTag.set(row.tag, existing);
270
+ }
271
+ return Array.from(byTag.entries())
272
+ .map(([tag, coverage]) => ({ tag, label: titleCase(tag), coverage }))
273
+ .sort((a, b) => a.tag.localeCompare(b.tag));
274
+ }
166
275
  pruneExpired() {
167
- const objectsCutoff = new Date(Date.now() - OBJECT_TTL_DAYS * MS_PER_DAY).toISOString();
168
- const queriesCutoff = new Date(Date.now() - QUERY_TTL_DAYS * MS_PER_DAY).toISOString();
169
- const objects = this.db.prepare(`DELETE FROM objects WHERE cached_at < ?`).run(objectsCutoff);
170
- const queries = this.db.prepare(`DELETE FROM query_cache WHERE cached_at < ?`).run(queriesCutoff);
276
+ const objects = this.db.prepare(`DELETE FROM objects WHERE cached_at < ?`).run(this.objectsCutoff());
277
+ const queries = this.db.prepare(`DELETE FROM query_cache WHERE cached_at < ?`).run(this.queriesCutoff());
171
278
  return { objects: objects.changes, queries: queries.changes };
172
279
  }
173
280
  isExpired(isoTimestamp, ttlDays) {
package/dist/db.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,eAAe,GAAG,EAAE,CAAC;AAC3B,MAAM,cAAc,GAAG,EAAE,CAAC;AAC1B,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEvC,yEAAyE;AACzE,4EAA4E;AAC5E,wEAAwE;AACxE,4DAA4D;AAC5D,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AACpD,CAAC;AAoBD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,KAAK;IACR,EAAE,CAAoB;IAE9B,YAAY,MAAmB;QAC7B,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACtC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,oEAAoE;YACpE,sEAAsE;YACtE,2CAA2C;YAC3C,IAAI,CAAC;gBACH,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,kEAAkE;YACpE,CAAC;QACH,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAEO,IAAI;QACV,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAuCZ,CAAC,CAAC;IACL,CAAC;IAED,YAAY,CAAC,GAAY;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;KAuB5B,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC;YACP,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI;YAC5B,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI;YAC5B,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,eAAe;YAC5C,YAAY,EAAE,GAAG,CAAC,WAAW;YAC7B,UAAU,EAAE,GAAG,CAAC,SAAS;YACzB,QAAQ,EAAE,GAAG,CAAC,OAAO;YACrB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI;YAC9B,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;YAChC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,MAAsB;QACpC,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,MAAM,MAAM,GAAwB,EAAE,CAAC;QAEvC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACnC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACjC,CAAC;QACD,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/D,UAAU,CAAC,IAAI,CAAC,uBAAuB,YAAY,GAAG,CAAC,CAAC;YACxD,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QACnC,CAAC;QACD,uEAAuE;QACvE,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,eAAe,GAAG,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAE/E,MAAM,KAAK,GAAG,SAAS,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAClD,MAAM,GAAG,GAAG,mCAAmC,KAAK,4BAA4B,CAAC;QACjF,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAwC,CAAC;QACvF,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAY,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,SAAS,CAAC,EAAU;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,yDAAyD,CAAC,CAAC,GAAG,CAAC,EAAE,CAEhF,CAAC;QACd,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,eAAe,CAAC;YAAE,OAAO,IAAI,CAAC;QAChE,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAY,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;YACpE,sEAAsE;YACtE,0DAA0D;YAC1D,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,QAAgB,EAAE,GAAa;QACtC,IAAI,CAAC,EAAE;aACJ,OAAO,CACN;;2GAEmG,CACpG;aACA,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,QAAQ,CAAC,QAAgB;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,iEAAiE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAE9F,CAAC;QACd,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/D,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAa,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;;;;;;OASG;IACH,cAAc;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC;YAC9C,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC;SAC/C,CAAC;IACJ,CAAC;IAEO,aAAa;QACnB,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,eAAe,GAAG,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3E,CAAC;IAEO,aAAa;QACnB,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,GAAG,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1E,CAAC;IAED,uEAAuE;IACvE,oEAAoE;IACpE,0EAA0E;IAC1E,yEAAyE;IACzE,sEAAsE;IACtE,6CAA6C;IACrC,cAAc,CAAC,MAA2B,EAAE,MAAc;QAChE,MAAM,GAAG,GACP,MAAM,KAAK,QAAQ;YACjB,CAAC,CAAC;;;+CAGqC;YACvC,CAAC,CAAC;;;+CAGqC,CAAC;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAI1C,CAAC;QAEH,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkC,CAAC;QACxD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,+DAA+D;YAC/D,gEAAgE;YAChE,4CAA4C;YAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC3D,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC;YACpC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC/B,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;aAC/B,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;aACpE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,YAAY;QACV,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QACrG,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,6CAA6C,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QACzG,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IAChE,CAAC;IAEO,SAAS,CAAC,YAAoB,EAAE,OAAe;QACrD,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;QAClD,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;QAClD,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAChC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ import type { Fetcher } from './types.js';
2
+ export declare const aicFetcher: Fetcher;
@@ -0,0 +1,168 @@
1
+ import { parseDisplayDate } from '../dateParser.js';
2
+ import { validateAicLicense } from '../licenseGate.js';
3
+ import { cleanArtistName, detectAttributionType, normalizeRegion } from '../mappings.js';
4
+ import { asFiniteNumber, asOptionalString, asString } from './helpers.js';
5
+ const AIC_API = 'https://api.artic.edu/api/v1';
6
+ const AIC_IIIF = 'https://www.artic.edu/iiif/2';
7
+ const AIC_PAGE = 'https://www.artic.edu/artworks';
8
+ // Fields requested from /artworks/{id}. Limiting via ?fields= shrinks the
9
+ // payload roughly 10x compared with the default response (which carries
10
+ // every relationship and provenance entry AIC has).
11
+ const AIC_FIELDS = [
12
+ 'id',
13
+ 'title',
14
+ 'is_public_domain',
15
+ 'artist_display',
16
+ 'artist_title',
17
+ 'date_display',
18
+ 'date_start',
19
+ 'date_end',
20
+ 'place_of_origin',
21
+ 'medium_display',
22
+ 'classification_title',
23
+ 'image_id',
24
+ ].join(',');
25
+ function reject(id, reason, rawSnapshot) {
26
+ return {
27
+ status: 'rejected',
28
+ rejection: { id, museumCode: 'aic', reason, rawSnapshot },
29
+ };
30
+ }
31
+ // AIC's `artist_display` format mirrors Cleveland's: "Name (Nationality,
32
+ // birthYear–deathYear)". The structured `artist_title` field gives us the
33
+ // canonical name without the parenthetical, so we use that and only mine
34
+ // the display string for nationality and lifespan.
35
+ function looksLikeNationality(token) {
36
+ // Nationality words are short, alphabetic, no digits, and don't start with
37
+ // "born" (which AIC sometimes uses for living artists, e.g.
38
+ // "X (born 1950)"). The strict shape check here keeps year tokens and
39
+ // birth-line tokens out of the nationality field.
40
+ return token.length > 0 && !/\d/.test(token) && !/^born\b/i.test(token);
41
+ }
42
+ function parseArtistDisplay(display) {
43
+ const parenStart = display.indexOf('(');
44
+ if (parenStart < 0)
45
+ return {};
46
+ const parenEnd = display.lastIndexOf(')');
47
+ const inside = parenEnd > parenStart ? display.slice(parenStart + 1, parenEnd) : '';
48
+ const tokens = inside.split(',').map((t) => t.trim()).filter(Boolean);
49
+ const nationality = tokens[0] && looksLikeNationality(tokens[0]) ? tokens[0] : undefined;
50
+ const yearLine = tokens.find((t) => /^\d{1,4}/.test(t) || /^born\b/i.test(t));
51
+ return { nationality, lifespan: yearLine || undefined };
52
+ }
53
+ export const aicFetcher = {
54
+ code: 'aic',
55
+ name: 'Art Institute of Chicago',
56
+ async search(query, limit, options = {}) {
57
+ const url = new URL(`${AIC_API}/artworks/search`);
58
+ url.searchParams.set('q', query);
59
+ // Push the rights filter to AIC server-side via Elasticsearch term
60
+ // query, so the gate has fewer rejections to handle. Defense in depth:
61
+ // validateAicLicense still re-checks each fetched record.
62
+ url.searchParams.set('query[term][is_public_domain]', 'true');
63
+ if (options.hasImage !== false) {
64
+ // exists query against image_id keeps records without IIIF imagery
65
+ // out of the candidate list.
66
+ url.searchParams.set('query[exists][field]', 'image_id');
67
+ }
68
+ url.searchParams.set('limit', String(limit));
69
+ url.searchParams.set('fields', 'id');
70
+ const res = await fetch(url);
71
+ if (!res.ok)
72
+ throw new Error(`AIC search failed: ${res.status}`);
73
+ const json = (await res.json());
74
+ const data = json.data ?? [];
75
+ return data
76
+ .map((d) => (typeof d.id === 'number' ? `aic:${d.id}` : null))
77
+ .filter((s) => s !== null)
78
+ .slice(0, limit);
79
+ },
80
+ async getRaw(id) {
81
+ const numeric = id.replace(/^aic:/, '');
82
+ const url = new URL(`${AIC_API}/artworks/${numeric}`);
83
+ url.searchParams.set('fields', AIC_FIELDS);
84
+ const res = await fetch(url);
85
+ if (!res.ok)
86
+ throw new Error(`AIC get failed for ${id}: ${res.status}`);
87
+ return res.json();
88
+ },
89
+ normalize(raw) {
90
+ if (!raw || typeof raw !== 'object') {
91
+ return reject('aic:unknown', 'aic: response not an object', raw);
92
+ }
93
+ // AIC wraps single-record responses in `{"data": {...}}`. Tolerate
94
+ // either shape (mirrors the Cleveland adapter pattern).
95
+ const wrapped = raw.data;
96
+ const inner = wrapped && typeof wrapped === 'object' ? wrapped : raw;
97
+ const r = inner;
98
+ const objectId = r.id;
99
+ const validId = typeof objectId === 'number' && Number.isInteger(objectId) && objectId > 0;
100
+ const id = validId ? `aic:${objectId}` : 'aic:unknown';
101
+ const decision = validateAicLicense(inner);
102
+ if (!decision.accepted || !decision.license) {
103
+ return reject(id, decision.reason, raw);
104
+ }
105
+ if (!validId) {
106
+ return reject(id, 'aic: missing or non-integer id', raw);
107
+ }
108
+ const displayDate = asString(r.date_display);
109
+ const dateStart = asFiniteNumber(r.date_start);
110
+ const dateEnd = asFiniteNumber(r.date_end);
111
+ // AIC ships date_start/date_end as integers. Trust them when both are
112
+ // present; fall back to parseDisplayDate otherwise so dynasty-aware
113
+ // parsing still helps for sparser records.
114
+ const dateRange = dateStart !== null && dateEnd !== null
115
+ ? { yearStart: dateStart, yearEnd: dateEnd }
116
+ : parseDisplayDate(displayDate);
117
+ const artistDisplay = asString(r.artist_display);
118
+ const artistTitle = asString(r.artist_title);
119
+ const attributionType = artistDisplay
120
+ ? detectAttributionType(artistDisplay)
121
+ : 'anonymous';
122
+ // Prefer `artist_title` (canonical name without the parenthetical).
123
+ // Fall back to mining `artist_display` if artist_title is missing.
124
+ const cleanName = cleanArtistName(artistTitle || artistDisplay.split('(')[0].trim());
125
+ const { nationality, lifespan } = parseArtistDisplay(artistDisplay);
126
+ const region = normalizeRegion(asString(r.place_of_origin));
127
+ const imageId = asString(r.image_id);
128
+ // AIC publishes through IIIF Image API 2.0. 843px-wide is AIC's
129
+ // standard public-display size; 200px-wide is the thumbnail tier.
130
+ const fullImage = imageId ? `${AIC_IIIF}/${imageId}/full/843,/0/default.jpg` : '';
131
+ const thumbnail = imageId ? `${AIC_IIIF}/${imageId}/full/200,/0/default.jpg` : undefined;
132
+ const artwork = {
133
+ id,
134
+ museum: {
135
+ code: 'aic',
136
+ name: 'Art Institute of Chicago',
137
+ url: 'https://www.artic.edu',
138
+ },
139
+ title: (asString(r.title) || '(Untitled)').trim(),
140
+ artist: {
141
+ name: cleanName || 'Unknown',
142
+ nationality,
143
+ lifespan,
144
+ attributionType,
145
+ },
146
+ displayDate,
147
+ yearStart: dateRange.yearStart,
148
+ yearEnd: dateRange.yearEnd,
149
+ medium: asString(r.medium_display),
150
+ region,
151
+ period: null,
152
+ imageUrls: {
153
+ full: fullImage,
154
+ thumbnail,
155
+ },
156
+ imageOpenAccess: decision.imageOpenAccess,
157
+ metadataOpenAccess: decision.metadataOpenAccess,
158
+ license: decision.license,
159
+ source: {
160
+ apiUrl: `${AIC_API}/artworks/${objectId}`,
161
+ pageUrl: `${AIC_PAGE}/${objectId}`,
162
+ },
163
+ description: asOptionalString(r.classification_title),
164
+ };
165
+ return { status: 'accepted', artwork };
166
+ },
167
+ };
168
+ //# sourceMappingURL=aic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aic.js","sourceRoot":"","sources":["../../src/fetchers/aic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEzF,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG1E,MAAM,OAAO,GAAG,8BAA8B,CAAC;AAC/C,MAAM,QAAQ,GAAG,8BAA8B,CAAC;AAChD,MAAM,QAAQ,GAAG,gCAAgC,CAAC;AAElD,0EAA0E;AAC1E,wEAAwE;AACxE,oDAAoD;AACpD,MAAM,UAAU,GAAG;IACjB,IAAI;IACJ,OAAO;IACP,kBAAkB;IAClB,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,YAAY;IACZ,UAAU;IACV,iBAAiB;IACjB,gBAAgB;IAChB,sBAAsB;IACtB,UAAU;CACX,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,SAAS,MAAM,CAAC,EAAU,EAAE,MAAc,EAAE,WAAoB;IAC9D,OAAO;QACL,MAAM,EAAE,UAAU;QAClB,SAAS,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE;KAC1D,CAAC;AACJ,CAAC;AAED,yEAAyE;AACzE,0EAA0E;AAC1E,yEAAyE;AACzE,mDAAmD;AACnD,SAAS,oBAAoB,CAAC,KAAa;IACzC,2EAA2E;IAC3E,4DAA4D;IAC5D,sEAAsE;IACtE,kDAAkD;IAClD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAe;IACzC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,UAAU,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpF,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACtE,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzF,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,IAAI,SAAS,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAY;IACjC,IAAI,EAAE,KAAK;IACX,IAAI,EAAE,0BAA0B;IAEhC,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,KAAa,EAAE,UAAyB,EAAE;QACpE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,OAAO,kBAAkB,CAAC,CAAC;QAClD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjC,mEAAmE;QACnE,uEAAuE;QACvE,0DAA0D;QAC1D,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,+BAA+B,EAAE,MAAM,CAAC,CAAC;QAC9D,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;YAC/B,mEAAmE;YACnE,6BAA6B;YAC7B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,sBAAsB,EAAE,UAAU,CAAC,CAAC;QAC3D,CAAC;QACD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAErC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuC,CAAC;QACtE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QAC7B,OAAO,IAAI;aACR,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aAC7D,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;aACtC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,OAAO,aAAa,OAAO,EAAE,CAAC,CAAC;QACtD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,EAAE,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACxE,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED,SAAS,CAAC,GAAY;QACpB,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YACpC,OAAO,MAAM,CAAC,aAAa,EAAE,6BAA6B,EAAE,GAAG,CAAC,CAAC;QACnE,CAAC;QACD,mEAAmE;QACnE,wDAAwD;QACxD,MAAM,OAAO,GAAI,GAA0B,CAAC,IAAI,CAAC;QACjD,MAAM,KAAK,GAAG,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;QACrE,MAAM,CAAC,GAAG,KAAgC,CAAC;QAE3C,MAAM,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC;QACtB,MAAM,OAAO,GACX,OAAO,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC;QAC7E,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,QAAQ,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAEvD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC5C,OAAO,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC1C,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,MAAM,CAAC,EAAE,EAAE,gCAAgC,EAAE,GAAG,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC3C,sEAAsE;QACtE,oEAAoE;QACpE,2CAA2C;QAC3C,MAAM,SAAS,GACb,SAAS,KAAK,IAAI,IAAI,OAAO,KAAK,IAAI;YACpC,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE;YAC5C,CAAC,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAEpC,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QAC7C,MAAM,eAAe,GAAG,aAAa;YACnC,CAAC,CAAC,qBAAqB,CAAC,aAAa,CAAC;YACtC,CAAC,CAAC,WAAW,CAAC;QAChB,oEAAoE;QACpE,mEAAmE;QACnE,MAAM,SAAS,GAAG,eAAe,CAAC,WAAW,IAAI,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACrF,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;QAEpE,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;QAE5D,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACrC,gEAAgE;QAChE,kEAAkE;QAClE,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,OAAO,0BAA0B,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,OAAO,0BAA0B,CAAC,CAAC,CAAC,SAAS,CAAC;QAEzF,MAAM,OAAO,GAAY;YACvB,EAAE;YACF,MAAM,EAAE;gBACN,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,0BAA0B;gBAChC,GAAG,EAAE,uBAAuB;aAC7B;YACD,KAAK,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,CAAC,IAAI,EAAE;YACjD,MAAM,EAAE;gBACN,IAAI,EAAE,SAAS,IAAI,SAAS;gBAC5B,WAAW;gBACX,QAAQ;gBACR,eAAe;aAChB;YACD,WAAW;YACX,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC;YAClC,MAAM;YACN,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE;gBACT,IAAI,EAAE,SAAS;gBACf,SAAS;aACV;YACD,eAAe,EAAE,QAAQ,CAAC,eAAe;YACzC,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB;YAC/C,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,MAAM,EAAE;gBACN,MAAM,EAAE,GAAG,OAAO,aAAa,QAAQ,EAAE;gBACzC,OAAO,EAAE,GAAG,QAAQ,IAAI,QAAQ,EAAE;aACnC;YACD,WAAW,EAAE,gBAAgB,CAAC,CAAC,CAAC,oBAAoB,CAAC;SACtD,CAAC;QAEF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;IACzC,CAAC;CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Fetcher } from './types.js';
2
+ export declare const clevelandFetcher: Fetcher;
@@ -0,0 +1,150 @@
1
+ import { parseDisplayDate } from '../dateParser.js';
2
+ import { validateClevelandLicense } from '../licenseGate.js';
3
+ import { cleanArtistName, detectAttributionType, normalizeRegion } from '../mappings.js';
4
+ import { asFiniteNumber, asOptionalString, asString } from './helpers.js';
5
+ const CLEVELAND_API = 'https://openaccess-api.clevelandart.org/api';
6
+ function reject(id, reason, rawSnapshot) {
7
+ return {
8
+ status: 'rejected',
9
+ rejection: { id, museumCode: 'cleveland', reason, rawSnapshot },
10
+ };
11
+ }
12
+ // Cleveland's creator description format is "Name (Nationality, birthYear–deathYear)"
13
+ // e.g. "Vincent van Gogh (Dutch, 1853–1890)". The structured fields
14
+ // (birth_year, death_year) supply the lifespan, so we only mine the
15
+ // description for name + nationality.
16
+ function parseCreatorDescription(description) {
17
+ const parenStart = description.indexOf('(');
18
+ if (parenStart < 0)
19
+ return { name: description.trim() };
20
+ const name = description.slice(0, parenStart).trim();
21
+ const parenEnd = description.lastIndexOf(')');
22
+ const inside = parenEnd > parenStart ? description.slice(parenStart + 1, parenEnd) : '';
23
+ const firstToken = inside.split(',')[0].trim();
24
+ // If the first token looks like a year, the description omitted nationality
25
+ // ("Anonymous (1850)") and we should not surface it.
26
+ const looksLikeYear = /^\d{2,4}$/.test(firstToken);
27
+ return looksLikeYear || !firstToken ? { name } : { name, nationality: firstToken };
28
+ }
29
+ export const clevelandFetcher = {
30
+ code: 'cleveland',
31
+ name: 'Cleveland Museum of Art',
32
+ async search(query, limit, options = {}) {
33
+ const url = new URL(`${CLEVELAND_API}/artworks/`);
34
+ url.searchParams.set('q', query);
35
+ // Push the rights filter to the museum so the gate has fewer rejections to
36
+ // handle. Cleveland's `cc0=1` is server-side defense in depth alongside
37
+ // the per-record validateClevelandLicense check on every fetched object.
38
+ url.searchParams.set('cc0', '1');
39
+ if (options.hasImage !== false) {
40
+ url.searchParams.set('has_image', '1');
41
+ }
42
+ url.searchParams.set('limit', String(limit));
43
+ url.searchParams.set('fields', 'id');
44
+ const res = await fetch(url);
45
+ if (!res.ok)
46
+ throw new Error(`Cleveland search failed: ${res.status}`);
47
+ const json = (await res.json());
48
+ const data = json.data ?? [];
49
+ return data
50
+ .map((d) => (typeof d.id === 'number' ? `cleveland:${d.id}` : null))
51
+ .filter((s) => s !== null)
52
+ .slice(0, limit);
53
+ },
54
+ async getRaw(id) {
55
+ const numeric = id.replace(/^cleveland:/, '');
56
+ const res = await fetch(`${CLEVELAND_API}/artworks/${numeric}`);
57
+ if (!res.ok)
58
+ throw new Error(`Cleveland get failed for ${id}: ${res.status}`);
59
+ return res.json();
60
+ },
61
+ normalize(raw) {
62
+ if (!raw || typeof raw !== 'object') {
63
+ return reject('cleveland:unknown', 'cleveland: response not an object', raw);
64
+ }
65
+ // Cleveland wraps single-record responses in `{"data": {...}}`. Tolerate
66
+ // either shape so fixtures and direct-record callers both work.
67
+ const wrapped = raw.data;
68
+ const inner = wrapped && typeof wrapped === 'object' ? wrapped : raw;
69
+ const r = inner;
70
+ const objectId = r.id;
71
+ const validId = typeof objectId === 'number' && Number.isInteger(objectId) && objectId > 0;
72
+ const id = validId ? `cleveland:${objectId}` : 'cleveland:unknown';
73
+ const decision = validateClevelandLicense(inner);
74
+ if (!decision.accepted || !decision.license) {
75
+ return reject(id, decision.reason, raw);
76
+ }
77
+ if (!validId) {
78
+ return reject(id, 'cleveland: missing or non-integer id', raw);
79
+ }
80
+ const displayDate = asString(r.creation_date);
81
+ const earliest = asFiniteNumber(r.creation_date_earliest);
82
+ const latest = asFiniteNumber(r.creation_date_latest);
83
+ // Cleveland publishes earliest/latest year fields directly. Trust those
84
+ // when both are present; otherwise fall through to parseDisplayDate. We
85
+ // prefer the display-date parser over a single available bound because
86
+ // the displayDate string usually carries a richer signal — "1850s"
87
+ // parses to {1850, 1859}, more informative than an isolated
88
+ // creation_date_earliest=1850 with creation_date_latest missing.
89
+ const dateRange = earliest !== null && latest !== null
90
+ ? { yearStart: earliest, yearEnd: latest }
91
+ : parseDisplayDate(displayDate);
92
+ const creators = Array.isArray(r.creators)
93
+ ? r.creators
94
+ : [];
95
+ const primary = creators[0];
96
+ const description = asString(primary?.description);
97
+ const attributionType = detectAttributionType(description);
98
+ const parsed = parseCreatorDescription(description);
99
+ const cleanName = cleanArtistName(parsed.name);
100
+ const birth = asString(primary?.birth_year);
101
+ const death = asString(primary?.death_year);
102
+ const lifespan = birth || death ? `${birth}–${death}`.replace(/^–|–$/g, '') : undefined;
103
+ const cultureArr = Array.isArray(r.culture) ? r.culture : [];
104
+ const cultureStr = asString(cultureArr[0]);
105
+ const region = normalizeRegion(cultureStr);
106
+ const images = (r.images && typeof r.images === 'object' ? r.images : {});
107
+ const printVariant = images.print;
108
+ const webVariant = images.web;
109
+ // Prefer the higher-resolution `print` URL when both are available; fall
110
+ // back to `web` (smaller display image). The full TIFF is too large for
111
+ // most consumer use cases, so we don't surface it.
112
+ const fullImage = asString(printVariant?.url) || asString(webVariant?.url);
113
+ const thumbnail = asOptionalString(webVariant?.url);
114
+ const artwork = {
115
+ id,
116
+ museum: {
117
+ code: 'cleveland',
118
+ name: 'Cleveland Museum of Art',
119
+ url: 'https://www.clevelandart.org',
120
+ },
121
+ title: (asString(r.title) || '(Untitled)').trim(),
122
+ artist: {
123
+ name: cleanName || 'Unknown',
124
+ nationality: parsed.nationality,
125
+ lifespan,
126
+ attributionType,
127
+ },
128
+ displayDate,
129
+ yearStart: dateRange.yearStart,
130
+ yearEnd: dateRange.yearEnd,
131
+ medium: asString(r.technique),
132
+ region,
133
+ period: null,
134
+ imageUrls: {
135
+ full: fullImage,
136
+ thumbnail,
137
+ },
138
+ imageOpenAccess: decision.imageOpenAccess,
139
+ metadataOpenAccess: decision.metadataOpenAccess,
140
+ license: decision.license,
141
+ source: {
142
+ apiUrl: `${CLEVELAND_API}/artworks/${objectId}`,
143
+ pageUrl: asString(r.url),
144
+ },
145
+ description: asOptionalString(r.accession_number),
146
+ };
147
+ return { status: 'accepted', artwork };
148
+ },
149
+ };
150
+ //# sourceMappingURL=cleveland.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleveland.js","sourceRoot":"","sources":["../../src/fetchers/cleveland.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Shared coercion helpers for fetcher.normalize implementations.
3
+ *
4
+ * Each museum API ships fields that may be missing, null, or the wrong type.
5
+ * House style (per CONTRIBUTING.md) is to type uncertain shapes as `unknown`
6
+ * and narrow with explicit checks rather than casting with `as`. These
7
+ * helpers express the most-common narrowings once.
8
+ */
9
+ /** Returns the string value, or "" for any non-string input. */
10
+ export declare function asString(v: unknown): string;
11
+ /** Returns the trimmed-truthy string, or undefined for missing/empty/non-string. */
12
+ export declare function asOptionalString(v: unknown): string | undefined;
13
+ /** Returns finite number, or null for NaN/Infinity/non-number. */
14
+ export declare function asFiniteNumber(v: unknown): number | null;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Shared coercion helpers for fetcher.normalize implementations.
3
+ *
4
+ * Each museum API ships fields that may be missing, null, or the wrong type.
5
+ * House style (per CONTRIBUTING.md) is to type uncertain shapes as `unknown`
6
+ * and narrow with explicit checks rather than casting with `as`. These
7
+ * helpers express the most-common narrowings once.
8
+ */
9
+ /** Returns the string value, or "" for any non-string input. */
10
+ export function asString(v) {
11
+ return typeof v === 'string' ? v : '';
12
+ }
13
+ /** Returns the trimmed-truthy string, or undefined for missing/empty/non-string. */
14
+ export function asOptionalString(v) {
15
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
16
+ }
17
+ /** Returns finite number, or null for NaN/Infinity/non-number. */
18
+ export function asFiniteNumber(v) {
19
+ return typeof v === 'number' && Number.isFinite(v) ? v : null;
20
+ }
21
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/fetchers/helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,gEAAgE;AAChE,MAAM,UAAU,QAAQ,CAAC,CAAU;IACjC,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACxC,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,gBAAgB,CAAC,CAAU;IACzC,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/D,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,cAAc,CAAC,CAAU;IACvC,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAChE,CAAC"}
@@ -1,13 +1,8 @@
1
1
  import { parseDisplayDate } from '../dateParser.js';
2
2
  import { validateMetLicense } from '../licenseGate.js';
3
3
  import { cleanArtistName, detectAttributionType, normalizeRegion } from '../mappings.js';
4
+ import { asOptionalString, asString } from './helpers.js';
4
5
  const MET_API = 'https://collectionapi.metmuseum.org/public/collection/v1';
5
- function asString(v) {
6
- return typeof v === 'string' ? v : '';
7
- }
8
- function asOptionalString(v) {
9
- return typeof v === 'string' && v.length > 0 ? v : undefined;
10
- }
11
6
  export const metFetcher = {
12
7
  code: 'met',
13
8
  name: 'The Metropolitan Museum of Art',
@@ -1 +1 @@
1
- {"version":3,"file":"met.js","sourceRoot":"","sources":["../../src/fetchers/met.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"met.js","sourceRoot":"","sources":["../../src/fetchers/met.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -7,9 +7,13 @@ import { join } from 'node:path';
7
7
  import { z } from 'zod';
8
8
  import { cite } from './cite.js';
9
9
  import { Cache } from './db.js';
10
+ import { aicFetcher } from './fetchers/aic.js';
11
+ import { clevelandFetcher } from './fetchers/cleveland.js';
10
12
  import { metFetcher } from './fetchers/met.js';
11
13
  const FETCHERS = {
12
14
  [metFetcher.code]: metFetcher,
15
+ [clevelandFetcher.code]: clevelandFetcher,
16
+ [aicFetcher.code]: aicFetcher,
13
17
  };
14
18
  const CACHE_PATH = process.env.OMM_CACHE_PATH ?? join(homedir(), '.open-museum-mcp', 'cache.db');
15
19
  const cache = new Cache({ path: CACHE_PATH });
@@ -49,6 +53,12 @@ const CiteInput = z.object({
49
53
  id: z.string().regex(ID_REGEX),
50
54
  style: z.enum(['short', 'full', 'caption']).default('full'),
51
55
  });
56
+ const DiscoverInput = z.object({
57
+ region: z.string().min(1).optional(),
58
+ period: z.string().min(1).optional(),
59
+ not_artist: z.array(z.string().min(1)).optional(),
60
+ museum: z.string().min(1).optional(),
61
+ });
52
62
  async function fetchAndCache(id) {
53
63
  if (!ID_REGEX.test(id)) {
54
64
  return { ok: false, reason: `invalid artwork id: ${id}` };
@@ -90,7 +100,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
90
100
  query: { type: 'string', description: 'Free-text query.' },
91
101
  museum: {
92
102
  type: 'string',
93
- description: 'Optional museum code. Currently registered: met. (Cleveland, AIC adapters are planned for v0.2.)',
103
+ description: 'Optional museum code. Currently registered: met, cleveland, aic.',
94
104
  },
95
105
  has_image: {
96
106
  type: 'boolean',
@@ -129,6 +139,40 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
129
139
  required: ['id'],
130
140
  },
131
141
  },
142
+ {
143
+ name: 'discover_random',
144
+ description: '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). Operates over what has already been searched and cached; returns an error if nothing matches, suggesting the caller seed the cache via search_artworks first.',
145
+ inputSchema: {
146
+ type: 'object',
147
+ properties: {
148
+ region: {
149
+ type: 'string',
150
+ description: 'Normalized region tag (e.g. "china", "japan", "netherlands"). Exact match.',
151
+ },
152
+ period: {
153
+ type: 'string',
154
+ description: 'Normalized period tag (e.g. "tang dynasty", "edo", "safavid"). Exact match.',
155
+ },
156
+ not_artist: {
157
+ type: 'array',
158
+ items: { type: 'string' },
159
+ description: 'Artist names to exclude (exact match against the canonical artist name field).',
160
+ },
161
+ museum: {
162
+ type: 'string',
163
+ description: 'Optional museum code to restrict to (met, cleveland, aic).',
164
+ },
165
+ },
166
+ },
167
+ },
168
+ {
169
+ name: 'list_traditions',
170
+ description: '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 } }.',
171
+ inputSchema: {
172
+ type: 'object',
173
+ properties: {},
174
+ },
175
+ },
132
176
  ],
133
177
  }));
134
178
  function errorResult(message) {
@@ -190,6 +234,26 @@ async function handleCite(args) {
190
234
  return errorResult(out.reason);
191
235
  return { content: [{ type: 'text', text: cite(out.artwork, input.style) }] };
192
236
  }
237
+ async function handleDiscoverRandom(args) {
238
+ const input = DiscoverInput.parse(args);
239
+ if (input.museum && !FETCHERS[input.museum]) {
240
+ return errorResult(`unknown museum: ${input.museum}`);
241
+ }
242
+ const artwork = cache.getRandomObject({
243
+ region: input.region,
244
+ period: input.period,
245
+ notArtist: input.not_artist,
246
+ museumCode: input.museum,
247
+ });
248
+ if (!artwork) {
249
+ return errorResult('No cached artwork matches these constraints. Seed the cache with search_artworks first; discover_random samples from records you have already pulled.');
250
+ }
251
+ return { content: [{ type: 'text', text: JSON.stringify(artwork, null, 2) }] };
252
+ }
253
+ function handleListTraditions() {
254
+ const traditions = cache.listTraditions();
255
+ return { content: [{ type: 'text', text: JSON.stringify(traditions, null, 2) }] };
256
+ }
193
257
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
194
258
  const { name, arguments: args } = request.params;
195
259
  try {
@@ -199,6 +263,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
199
263
  return await handleGet(args);
200
264
  if (name === 'cite')
201
265
  return await handleCite(args);
266
+ if (name === 'discover_random')
267
+ return await handleDiscoverRandom(args);
268
+ if (name === 'list_traditions')
269
+ return handleListTraditions();
202
270
  return errorResult(`unknown tool: ${name}`);
203
271
  }
204
272
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -77,9 +77,10 @@ export interface DateRange {
77
77
  yearEnd: number | null;
78
78
  }
79
79
  /**
80
- * Reserved for v0.2 list_traditions tool: each normalized tradition tag will
81
- * carry per-museum coverage counts so callers can see where holdings live
82
- * before searching. Not yet emitted by any tool.
80
+ * One tradition tag (a normalized region or period) plus per-museum
81
+ * coverage counts in the local cache. Emitted by the `list_traditions`
82
+ * tool so callers can see where holdings are well-represented and where
83
+ * they're sparse before searching.
83
84
  */
84
85
  export interface Tradition {
85
86
  tag: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-museum-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "MCP server for license-verified search across open-access museum collections (The Met, Cleveland, AIC and more).",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",