@cyanheads/libofcongress-mcp-server 0.2.1
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/AGENTS.md +388 -0
- package/CLAUDE.md +388 -0
- package/Dockerfile +83 -0
- package/LICENSE +201 -0
- package/README.md +316 -0
- package/changelog/0.1.x/0.1.0.md +22 -0
- package/changelog/0.1.x/0.1.1.md +29 -0
- package/changelog/0.2.x/0.2.0.md +13 -0
- package/changelog/0.2.x/0.2.1.md +14 -0
- package/changelog/template.md +119 -0
- package/dist/config/server-config.d.ts +13 -0
- package/dist/config/server-config.d.ts.map +1 -0
- package/dist/config/server-config.js +25 -0
- package/dist/config/server-config.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/resources/definitions/libofcongress-item.resource.d.ts +9 -0
- package/dist/mcp-server/resources/definitions/libofcongress-item.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/libofcongress-item.resource.js +24 -0
- package/dist/mcp-server/resources/definitions/libofcongress-item.resource.js.map +1 -0
- package/dist/mcp-server/tools/definitions/libofcongress-browse-collections.tool.d.ts +35 -0
- package/dist/mcp-server/tools/definitions/libofcongress-browse-collections.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/libofcongress-browse-collections.tool.js +119 -0
- package/dist/mcp-server/tools/definitions/libofcongress-browse-collections.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/libofcongress-get-item.tool.d.ts +32 -0
- package/dist/mcp-server/tools/definitions/libofcongress-get-item.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/libofcongress-get-item.tool.js +97 -0
- package/dist/mcp-server/tools/definitions/libofcongress-get-item.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/libofcongress-get-newspaper-page.tool.d.ts +29 -0
- package/dist/mcp-server/tools/definitions/libofcongress-get-newspaper-page.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/libofcongress-get-newspaper-page.tool.js +89 -0
- package/dist/mcp-server/tools/definitions/libofcongress-get-newspaper-page.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/libofcongress-search-newspapers.tool.d.ts +40 -0
- package/dist/mcp-server/tools/definitions/libofcongress-search-newspapers.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/libofcongress-search-newspapers.tool.js +162 -0
- package/dist/mcp-server/tools/definitions/libofcongress-search-newspapers.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/libofcongress-search-subjects.tool.d.ts +24 -0
- package/dist/mcp-server/tools/definitions/libofcongress-search-subjects.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/libofcongress-search-subjects.tool.js +86 -0
- package/dist/mcp-server/tools/definitions/libofcongress-search-subjects.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/libofcongress-search.tool.d.ts +50 -0
- package/dist/mcp-server/tools/definitions/libofcongress-search.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/libofcongress-search.tool.js +171 -0
- package/dist/mcp-server/tools/definitions/libofcongress-search.tool.js.map +1 -0
- package/dist/services/lc-linked-data/lc-linked-data-service.d.ts +17 -0
- package/dist/services/lc-linked-data/lc-linked-data-service.d.ts.map +1 -0
- package/dist/services/lc-linked-data/lc-linked-data-service.js +71 -0
- package/dist/services/lc-linked-data/lc-linked-data-service.js.map +1 -0
- package/dist/services/lc-linked-data/types.d.ts +11 -0
- package/dist/services/lc-linked-data/types.d.ts.map +1 -0
- package/dist/services/lc-linked-data/types.js +6 -0
- package/dist/services/lc-linked-data/types.js.map +1 -0
- package/dist/services/loc-api/loc-api-service.d.ts +65 -0
- package/dist/services/loc-api/loc-api-service.d.ts.map +1 -0
- package/dist/services/loc-api/loc-api-service.js +418 -0
- package/dist/services/loc-api/loc-api-service.js.map +1 -0
- package/dist/services/loc-api/types.d.ts +156 -0
- package/dist/services/loc-api/types.d.ts.map +1 -0
- package/dist/services/loc-api/types.js +6 -0
- package/dist/services/loc-api/types.js.map +1 -0
- package/package.json +92 -0
- package/server.json +127 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview libofcongress_search tool — search Library of Congress digital collections.
|
|
3
|
+
* @module mcp-server/tools/definitions/libofcongress-search.tool
|
|
4
|
+
*/
|
|
5
|
+
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { JsonRpcErrorCode, validationError } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
+
import { getLocApiService } from '../../../services/loc-api/loc-api-service.js';
|
|
8
|
+
export const locSearch = tool('libofcongress_search', {
|
|
9
|
+
title: 'Search LOC Collections',
|
|
10
|
+
description: 'Search the Library of Congress digital collections by keyword. Optionally filter by material format (photos, maps, newspapers, audio, etc.), date range, subject heading, or geographic location. Returns item summaries with titles, dates, descriptions, LOC IDs, and format tags. Use libofcongress_get_item to retrieve full metadata for a specific result. Use libofcongress_search_subjects first to find the exact LCSH heading spelling before applying a subject filter.',
|
|
11
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
12
|
+
input: z.object({
|
|
13
|
+
query: z
|
|
14
|
+
.string()
|
|
15
|
+
.min(1)
|
|
16
|
+
.describe('Full-text search across metadata and available descriptive text.'),
|
|
17
|
+
format: z
|
|
18
|
+
.enum(['photo', 'map', 'newspaper', 'manuscript', 'audio', 'film', 'book', 'notated-music'])
|
|
19
|
+
.optional()
|
|
20
|
+
.describe('Material type filter. Options: photo, map, newspaper, manuscript, audio, film, book, notated-music. Omit to search all formats.'),
|
|
21
|
+
date_start: z
|
|
22
|
+
.number()
|
|
23
|
+
.int()
|
|
24
|
+
.optional()
|
|
25
|
+
.describe('Start year for date filter, inclusive (e.g., 1920). Omit for no lower bound.'),
|
|
26
|
+
date_end: z
|
|
27
|
+
.number()
|
|
28
|
+
.int()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('End year for date filter, inclusive (e.g., 1930). Omit for no upper bound.'),
|
|
31
|
+
subject: z
|
|
32
|
+
.string()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe('Subject heading filter. Use the exact label from libofcongress_search_subjects results for best precision. Example: "World War, 1939-1945".'),
|
|
35
|
+
location: z
|
|
36
|
+
.string()
|
|
37
|
+
.optional()
|
|
38
|
+
.describe('Geographic location filter (e.g., "oklahoma", "washington d.c."). Lowercase, matches LOC location facets.'),
|
|
39
|
+
limit: z
|
|
40
|
+
.number()
|
|
41
|
+
.int()
|
|
42
|
+
.min(1)
|
|
43
|
+
.max(100)
|
|
44
|
+
.default(25)
|
|
45
|
+
.describe('Results per page. Default 25, max 100.'),
|
|
46
|
+
page: z
|
|
47
|
+
.number()
|
|
48
|
+
.int()
|
|
49
|
+
.min(1)
|
|
50
|
+
.default(1)
|
|
51
|
+
.describe('1-indexed page number for paginating results.'),
|
|
52
|
+
}),
|
|
53
|
+
output: z.object({
|
|
54
|
+
items: z
|
|
55
|
+
.array(z
|
|
56
|
+
.object({
|
|
57
|
+
id: z
|
|
58
|
+
.string()
|
|
59
|
+
.describe('LOC item ID — pass to libofcongress_get_item for full metadata.'),
|
|
60
|
+
title: z.string().describe('Item title.'),
|
|
61
|
+
date: z.string().optional().describe('Publication or creation date.'),
|
|
62
|
+
description: z.string().optional().describe('Brief description or summary.'),
|
|
63
|
+
format: z
|
|
64
|
+
.string()
|
|
65
|
+
.optional()
|
|
66
|
+
.describe('Material format (e.g., photo, map, manuscript).'),
|
|
67
|
+
url: z.string().describe('LOC item URL.'),
|
|
68
|
+
})
|
|
69
|
+
.describe('A single LOC item summary.'))
|
|
70
|
+
.describe('Item summaries matching the search query and filters.'),
|
|
71
|
+
total: z.number().describe('Total number of matching items across all pages.'),
|
|
72
|
+
page: z.number().describe('Current 1-indexed page number.'),
|
|
73
|
+
pages: z.number().describe('Total number of pages available.'),
|
|
74
|
+
has_next: z.boolean().describe('True when more pages are available after this one.'),
|
|
75
|
+
message: z
|
|
76
|
+
.string()
|
|
77
|
+
.optional()
|
|
78
|
+
.describe('Recovery hint when results are empty — echoes the applied filters and suggests how to broaden. Absent on non-empty result pages.'),
|
|
79
|
+
}),
|
|
80
|
+
errors: [
|
|
81
|
+
{
|
|
82
|
+
reason: 'empty_results',
|
|
83
|
+
code: JsonRpcErrorCode.NotFound,
|
|
84
|
+
when: 'No items matched the query and filters.',
|
|
85
|
+
recovery: 'Broaden the query, widen the date range, or use libofcongress_search_subjects to find the correct subject heading spelling.',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
reason: 'rate_limit_exceeded',
|
|
89
|
+
code: JsonRpcErrorCode.ServiceUnavailable,
|
|
90
|
+
when: 'LOC API rate limit exceeded; requests are blocked for approximately 1 hour.',
|
|
91
|
+
recovery: 'Wait approximately 1 hour before retrying. Reduce request frequency to stay under 20 req/min.',
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
async handler(input, ctx) {
|
|
95
|
+
ctx.log.info('libofcongress_search', {
|
|
96
|
+
query: input.query,
|
|
97
|
+
format: input.format,
|
|
98
|
+
page: input.page,
|
|
99
|
+
});
|
|
100
|
+
if (input.date_start !== undefined &&
|
|
101
|
+
input.date_end !== undefined &&
|
|
102
|
+
input.date_start > input.date_end) {
|
|
103
|
+
throw validationError(`date_start (${input.date_start}) must be ≤ date_end (${input.date_end}). Reverse the values to form a valid date range.`, { field: 'date_start', date_start: input.date_start, date_end: input.date_end });
|
|
104
|
+
}
|
|
105
|
+
const svc = getLocApiService();
|
|
106
|
+
const result = await svc.search({
|
|
107
|
+
query: input.query,
|
|
108
|
+
...(input.format !== undefined && { format: input.format }),
|
|
109
|
+
...(input.date_start !== undefined && { dateStart: input.date_start }),
|
|
110
|
+
...(input.date_end !== undefined && { dateEnd: input.date_end }),
|
|
111
|
+
...(input.subject?.trim() && { subject: input.subject.trim() }),
|
|
112
|
+
...(input.location?.trim() && { location: input.location.trim() }),
|
|
113
|
+
limit: input.limit,
|
|
114
|
+
page: input.page,
|
|
115
|
+
}, ctx);
|
|
116
|
+
if (result.items.length === 0) {
|
|
117
|
+
return {
|
|
118
|
+
items: [],
|
|
119
|
+
total: 0,
|
|
120
|
+
page: input.page,
|
|
121
|
+
pages: 0,
|
|
122
|
+
has_next: false,
|
|
123
|
+
message: `No items matched "${input.query}"` +
|
|
124
|
+
(input.format ? ` with format "${input.format}"` : '') +
|
|
125
|
+
(input.date_start || input.date_end
|
|
126
|
+
? ` in dates ${input.date_start ?? ''}–${input.date_end ?? ''}`
|
|
127
|
+
: '') +
|
|
128
|
+
'. Try broadening the query, widening the date range, or running libofcongress_search_subjects to find the exact subject heading.',
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const { total, page, pages, hasNext } = result.pagination;
|
|
132
|
+
// Detect contradictory pagination: LOC sometimes returns items on out-of-range pages.
|
|
133
|
+
// Surface a clear message rather than a confusing "Page 999 of 26" display.
|
|
134
|
+
if (pages > 0 && page > pages) {
|
|
135
|
+
return {
|
|
136
|
+
items: [],
|
|
137
|
+
total,
|
|
138
|
+
page,
|
|
139
|
+
pages,
|
|
140
|
+
has_next: false,
|
|
141
|
+
message: `No results on page ${page} — query has ${pages} page(s) total (${total} items). Use a page number between 1 and ${pages}.`,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
items: result.items,
|
|
146
|
+
total,
|
|
147
|
+
page,
|
|
148
|
+
pages,
|
|
149
|
+
has_next: hasNext,
|
|
150
|
+
};
|
|
151
|
+
},
|
|
152
|
+
format: (result) => {
|
|
153
|
+
const lines = [];
|
|
154
|
+
lines.push(`**Total:** ${result.total} | **Page:** ${result.page} of ${result.pages} | **has_next:** ${result.has_next}`);
|
|
155
|
+
if (result.message)
|
|
156
|
+
lines.push(`\n> ${result.message}`);
|
|
157
|
+
for (const item of result.items) {
|
|
158
|
+
lines.push(`\n## ${item.title}`);
|
|
159
|
+
lines.push(`**ID:** ${item.id}`);
|
|
160
|
+
if (item.date)
|
|
161
|
+
lines.push(`**Date:** ${item.date}`);
|
|
162
|
+
if (item.format)
|
|
163
|
+
lines.push(`**Format:** ${item.format}`);
|
|
164
|
+
if (item.description)
|
|
165
|
+
lines.push(item.description);
|
|
166
|
+
lines.push(`**URL:** ${item.url}`);
|
|
167
|
+
}
|
|
168
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
//# sourceMappingURL=libofcongress-search.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"libofcongress-search.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/libofcongress-search.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview LC Linked Data service — wraps id.loc.gov for LCSH subject heading lookups.
|
|
3
|
+
* @module services/lc-linked-data/lc-linked-data-service
|
|
4
|
+
*/
|
|
5
|
+
import type { Context } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import type { AppConfig } from '@cyanheads/mcp-ts-core/config';
|
|
7
|
+
import type { StorageService } from '@cyanheads/mcp-ts-core/storage';
|
|
8
|
+
import type { LcSubjectHeading } from './types.js';
|
|
9
|
+
export declare class LcLinkedDataService {
|
|
10
|
+
private readonly userAgent;
|
|
11
|
+
constructor(_config: AppConfig, _storage: StorageService);
|
|
12
|
+
/** Search LCSH subject headings via the suggest endpoint */
|
|
13
|
+
searchSubjects(query: string, limit: number, ctx: Context): Promise<LcSubjectHeading[]>;
|
|
14
|
+
}
|
|
15
|
+
export declare function initLcLinkedDataService(config: AppConfig, storage: StorageService): void;
|
|
16
|
+
export declare function getLcLinkedDataService(): LcLinkedDataService;
|
|
17
|
+
//# sourceMappingURL=lc-linked-data-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lc-linked-data-service.d.ts","sourceRoot":"","sources":["../../../src/services/lc-linked-data/lc-linked-data-service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAWnD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc;IAKxD,4DAA4D;IACtD,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CA8C9F;AAMD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAExF;AAED,wBAAgB,sBAAsB,IAAI,mBAAmB,CAO5D"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview LC Linked Data service — wraps id.loc.gov for LCSH subject heading lookups.
|
|
3
|
+
* @module services/lc-linked-data/lc-linked-data-service
|
|
4
|
+
*/
|
|
5
|
+
import { serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
|
|
6
|
+
import { getServerConfig } from '../../config/server-config.js';
|
|
7
|
+
const LC_LINKED_DATA_BASE = 'https://id.loc.gov';
|
|
8
|
+
const SUBJECTS_SCHEME = 'http://id.loc.gov/authorities/subjects';
|
|
9
|
+
export class LcLinkedDataService {
|
|
10
|
+
userAgent;
|
|
11
|
+
constructor(_config, _storage) {
|
|
12
|
+
const serverConfig = getServerConfig();
|
|
13
|
+
this.userAgent = serverConfig.userAgent;
|
|
14
|
+
}
|
|
15
|
+
/** Search LCSH subject headings via the suggest endpoint */
|
|
16
|
+
async searchSubjects(query, limit, ctx) {
|
|
17
|
+
const qs = new URLSearchParams({
|
|
18
|
+
q: query,
|
|
19
|
+
memberOf: SUBJECTS_SCHEME,
|
|
20
|
+
count: String(Math.min(limit, 50)),
|
|
21
|
+
});
|
|
22
|
+
const url = `${LC_LINKED_DATA_BASE}/suggest/?${qs}`;
|
|
23
|
+
ctx.log.debug('LC Linked Data subject suggest', { url });
|
|
24
|
+
const response = await fetch(url, {
|
|
25
|
+
headers: { 'User-Agent': this.userAgent, Accept: 'application/json' },
|
|
26
|
+
signal: ctx.signal,
|
|
27
|
+
});
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
throw serviceUnavailable(`LC Linked Data returned HTTP ${response.status}`, {
|
|
30
|
+
url,
|
|
31
|
+
status: response.status,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
const text = await response.text();
|
|
35
|
+
if (/^\s*<(!DOCTYPE\s+html|html[\s>])/i.test(text)) {
|
|
36
|
+
throw serviceUnavailable('LC Linked Data returned HTML — temporarily unavailable.', { url });
|
|
37
|
+
}
|
|
38
|
+
const data = JSON.parse(text);
|
|
39
|
+
if (!Array.isArray(data) || data.length < 4) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
const [, labels, counts, uris] = data;
|
|
43
|
+
const results = [];
|
|
44
|
+
for (let i = 0; i < labels.length; i++) {
|
|
45
|
+
const label = labels[i];
|
|
46
|
+
const uri = uris[i];
|
|
47
|
+
if (!label || !uri)
|
|
48
|
+
continue;
|
|
49
|
+
const countStr = counts[i];
|
|
50
|
+
const count = countStr ? parseInt(countStr, 10) : undefined;
|
|
51
|
+
results.push({
|
|
52
|
+
label,
|
|
53
|
+
uri,
|
|
54
|
+
...(count !== undefined && !Number.isNaN(count) && { count }),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return results;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// --- Init/accessor pattern ---
|
|
61
|
+
let _service;
|
|
62
|
+
export function initLcLinkedDataService(config, storage) {
|
|
63
|
+
_service = new LcLinkedDataService(config, storage);
|
|
64
|
+
}
|
|
65
|
+
export function getLcLinkedDataService() {
|
|
66
|
+
if (!_service) {
|
|
67
|
+
throw new Error('LcLinkedDataService not initialized — call initLcLinkedDataService() in setup()');
|
|
68
|
+
}
|
|
69
|
+
return _service;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=lc-linked-data-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lc-linked-data-service.js","sourceRoot":"","sources":["../../../src/services/lc-linked-data/lc-linked-data-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Domain types for the LC Linked Data service (id.loc.gov).
|
|
3
|
+
* @module services/lc-linked-data/types
|
|
4
|
+
*/
|
|
5
|
+
/** Normalized LCSH subject heading record */
|
|
6
|
+
export type LcSubjectHeading = {
|
|
7
|
+
label: string;
|
|
8
|
+
uri: string;
|
|
9
|
+
count?: number;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/lc-linked-data/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,6CAA6C;AAC7C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/lc-linked-data/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview LOC JSON API service — wraps www.loc.gov with rate limiting, retry, and response normalization.
|
|
3
|
+
* @module services/loc-api/loc-api-service
|
|
4
|
+
*/
|
|
5
|
+
import type { Context } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import type { AppConfig } from '@cyanheads/mcp-ts-core/config';
|
|
7
|
+
import type { StorageService } from '@cyanheads/mcp-ts-core/storage';
|
|
8
|
+
import type { LocCollection, LocItemDetail, LocItemSummary, LocNewspaperPage, LocNewspaperPageDetail, LocPagination } from './types.js';
|
|
9
|
+
export declare class LocApiService {
|
|
10
|
+
private readonly userAgent;
|
|
11
|
+
private readonly requestDelayMs;
|
|
12
|
+
constructor(_config: AppConfig, _storage: StorageService);
|
|
13
|
+
private checkRateLimit;
|
|
14
|
+
private fetch;
|
|
15
|
+
private fetchJson;
|
|
16
|
+
/**
|
|
17
|
+
* Fetch a LOC search endpoint, treating HTTP 400 and 520 as out-of-range page responses
|
|
18
|
+
* (LOC returns these for page numbers beyond the result set).
|
|
19
|
+
* Returns null when the page is out of range.
|
|
20
|
+
*/
|
|
21
|
+
private fetchSearchJson;
|
|
22
|
+
/** Search LOC digital collections */
|
|
23
|
+
search(params: {
|
|
24
|
+
query: string;
|
|
25
|
+
format?: string;
|
|
26
|
+
dateStart?: number;
|
|
27
|
+
dateEnd?: number;
|
|
28
|
+
subject?: string;
|
|
29
|
+
location?: string;
|
|
30
|
+
limit?: number;
|
|
31
|
+
page?: number;
|
|
32
|
+
}, ctx: Context): Promise<{
|
|
33
|
+
items: LocItemSummary[];
|
|
34
|
+
pagination: LocPagination;
|
|
35
|
+
}>;
|
|
36
|
+
/** Get full metadata for a single LOC item */
|
|
37
|
+
getItem(itemId: string, ctx: Context): Promise<LocItemDetail>;
|
|
38
|
+
/** Search historical newspaper pages via the /newspapers/ endpoint */
|
|
39
|
+
searchNewspapers(params: {
|
|
40
|
+
query: string;
|
|
41
|
+
dateStart?: number;
|
|
42
|
+
dateEnd?: number;
|
|
43
|
+
state?: string;
|
|
44
|
+
newspaperTitle?: string;
|
|
45
|
+
limit?: number;
|
|
46
|
+
page?: number;
|
|
47
|
+
}, ctx: Context): Promise<{
|
|
48
|
+
items: LocNewspaperPage[];
|
|
49
|
+
pagination: LocPagination;
|
|
50
|
+
}>;
|
|
51
|
+
/** Retrieve full OCR text for a specific newspaper page via its resource URL */
|
|
52
|
+
getNewspaperPage(pageUrl: string, ctx: Context): Promise<LocNewspaperPageDetail>;
|
|
53
|
+
/** Browse LOC curated digital collections */
|
|
54
|
+
browseCollections(params: {
|
|
55
|
+
query?: string;
|
|
56
|
+
limit?: number;
|
|
57
|
+
page?: number;
|
|
58
|
+
}, ctx: Context): Promise<{
|
|
59
|
+
items: LocCollection[];
|
|
60
|
+
pagination: LocPagination;
|
|
61
|
+
}>;
|
|
62
|
+
}
|
|
63
|
+
export declare function initLocApiService(config: AppConfig, storage: StorageService): void;
|
|
64
|
+
export declare function getLocApiService(): LocApiService;
|
|
65
|
+
//# sourceMappingURL=loc-api-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loc-api-service.d.ts","sourceRoot":"","sources":["../../../src/services/loc-api/loc-api-service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAErE,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,aAAa,EAKd,MAAM,YAAY,CAAC;AAsFpB,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc;IAMxD,OAAO,CAAC,cAAc;YAgBR,KAAK;YAwCL,SAAS;IAevB;;;;OAIG;YACW,eAAe;IAoB7B,qCAAqC;IAC/B,MAAM,CACV,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,EACD,GAAG,EAAE,OAAO,GACX,OAAO,CAAC;QAAE,KAAK,EAAE,cAAc,EAAE,CAAC;QAAC,UAAU,EAAE,aAAa,CAAA;KAAE,CAAC;IA+BlE,8CAA8C;IACxC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC;IAgDnE,sEAAsE;IAChE,gBAAgB,CACpB,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,EACD,GAAG,EAAE,OAAO,GACX,OAAO,CAAC;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,UAAU,EAAE,aAAa,CAAA;KAAE,CAAC;IAmDpE,gFAAgF;IAC1E,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC;IA2FtF,6CAA6C;IACvC,iBAAiB,CACrB,MAAM,EAAE;QACN,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,EACD,GAAG,EAAE,OAAO,GACX,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,aAAa,CAAA;KAAE,CAAC;CAiClE;AAMD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAElF;AAED,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD"}
|