@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.
Files changed (64) hide show
  1. package/AGENTS.md +388 -0
  2. package/CLAUDE.md +388 -0
  3. package/Dockerfile +83 -0
  4. package/LICENSE +201 -0
  5. package/README.md +316 -0
  6. package/changelog/0.1.x/0.1.0.md +22 -0
  7. package/changelog/0.1.x/0.1.1.md +29 -0
  8. package/changelog/0.2.x/0.2.0.md +13 -0
  9. package/changelog/0.2.x/0.2.1.md +14 -0
  10. package/changelog/template.md +119 -0
  11. package/dist/config/server-config.d.ts +13 -0
  12. package/dist/config/server-config.d.ts.map +1 -0
  13. package/dist/config/server-config.js +25 -0
  14. package/dist/config/server-config.js.map +1 -0
  15. package/dist/index.d.ts +7 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +35 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/mcp-server/resources/definitions/libofcongress-item.resource.d.ts +9 -0
  20. package/dist/mcp-server/resources/definitions/libofcongress-item.resource.d.ts.map +1 -0
  21. package/dist/mcp-server/resources/definitions/libofcongress-item.resource.js +24 -0
  22. package/dist/mcp-server/resources/definitions/libofcongress-item.resource.js.map +1 -0
  23. package/dist/mcp-server/tools/definitions/libofcongress-browse-collections.tool.d.ts +35 -0
  24. package/dist/mcp-server/tools/definitions/libofcongress-browse-collections.tool.d.ts.map +1 -0
  25. package/dist/mcp-server/tools/definitions/libofcongress-browse-collections.tool.js +119 -0
  26. package/dist/mcp-server/tools/definitions/libofcongress-browse-collections.tool.js.map +1 -0
  27. package/dist/mcp-server/tools/definitions/libofcongress-get-item.tool.d.ts +32 -0
  28. package/dist/mcp-server/tools/definitions/libofcongress-get-item.tool.d.ts.map +1 -0
  29. package/dist/mcp-server/tools/definitions/libofcongress-get-item.tool.js +97 -0
  30. package/dist/mcp-server/tools/definitions/libofcongress-get-item.tool.js.map +1 -0
  31. package/dist/mcp-server/tools/definitions/libofcongress-get-newspaper-page.tool.d.ts +29 -0
  32. package/dist/mcp-server/tools/definitions/libofcongress-get-newspaper-page.tool.d.ts.map +1 -0
  33. package/dist/mcp-server/tools/definitions/libofcongress-get-newspaper-page.tool.js +89 -0
  34. package/dist/mcp-server/tools/definitions/libofcongress-get-newspaper-page.tool.js.map +1 -0
  35. package/dist/mcp-server/tools/definitions/libofcongress-search-newspapers.tool.d.ts +40 -0
  36. package/dist/mcp-server/tools/definitions/libofcongress-search-newspapers.tool.d.ts.map +1 -0
  37. package/dist/mcp-server/tools/definitions/libofcongress-search-newspapers.tool.js +162 -0
  38. package/dist/mcp-server/tools/definitions/libofcongress-search-newspapers.tool.js.map +1 -0
  39. package/dist/mcp-server/tools/definitions/libofcongress-search-subjects.tool.d.ts +24 -0
  40. package/dist/mcp-server/tools/definitions/libofcongress-search-subjects.tool.d.ts.map +1 -0
  41. package/dist/mcp-server/tools/definitions/libofcongress-search-subjects.tool.js +86 -0
  42. package/dist/mcp-server/tools/definitions/libofcongress-search-subjects.tool.js.map +1 -0
  43. package/dist/mcp-server/tools/definitions/libofcongress-search.tool.d.ts +50 -0
  44. package/dist/mcp-server/tools/definitions/libofcongress-search.tool.d.ts.map +1 -0
  45. package/dist/mcp-server/tools/definitions/libofcongress-search.tool.js +171 -0
  46. package/dist/mcp-server/tools/definitions/libofcongress-search.tool.js.map +1 -0
  47. package/dist/services/lc-linked-data/lc-linked-data-service.d.ts +17 -0
  48. package/dist/services/lc-linked-data/lc-linked-data-service.d.ts.map +1 -0
  49. package/dist/services/lc-linked-data/lc-linked-data-service.js +71 -0
  50. package/dist/services/lc-linked-data/lc-linked-data-service.js.map +1 -0
  51. package/dist/services/lc-linked-data/types.d.ts +11 -0
  52. package/dist/services/lc-linked-data/types.d.ts.map +1 -0
  53. package/dist/services/lc-linked-data/types.js +6 -0
  54. package/dist/services/lc-linked-data/types.js.map +1 -0
  55. package/dist/services/loc-api/loc-api-service.d.ts +65 -0
  56. package/dist/services/loc-api/loc-api-service.d.ts.map +1 -0
  57. package/dist/services/loc-api/loc-api-service.js +418 -0
  58. package/dist/services/loc-api/loc-api-service.js.map +1 -0
  59. package/dist/services/loc-api/types.d.ts +156 -0
  60. package/dist/services/loc-api/types.d.ts.map +1 -0
  61. package/dist/services/loc-api/types.js +6 -0
  62. package/dist/services/loc-api/types.js.map +1 -0
  63. package/package.json +92 -0
  64. package/server.json +127 -0
@@ -0,0 +1,89 @@
1
+ /**
2
+ * @fileoverview libofcongress_get_newspaper_page tool — retrieve full OCR text for a specific newspaper page.
3
+ * @module mcp-server/tools/definitions/libofcongress-get-newspaper-page.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
+ const LOC_PAGE_URL_PREFIX = 'https://www.loc.gov/resource/';
9
+ export const locGetNewspaperPage = tool('libofcongress_get_newspaper_page', {
10
+ title: 'Get Newspaper Page',
11
+ description: 'Retrieve the full OCR text of a specific historical newspaper page along with publication metadata. Pass the url field from a libofcongress_search_newspapers result — do not construct this URL manually. OCR quality varies by digitization batch and era: 19th-century and degraded materials may contain fragmented text, garbled words, and line-break artifacts that are surfaced as-is. When a page exists but has no digitized text, ocr_available is false and ocr_text is empty — this is a data property, not an error.',
12
+ annotations: { readOnlyHint: true, openWorldHint: true },
13
+ input: z.object({
14
+ page_url: z
15
+ .string()
16
+ .describe('The url field from a libofcongress_search_newspapers result. Format: https://www.loc.gov/resource/sn{number}/{date-id}.{seq}/. Always pass the value directly from search results — do not construct or modify this URL.'),
17
+ }),
18
+ output: z.object({
19
+ page_url: z.string().describe('The LOC resource URL for this newspaper page.'),
20
+ newspaper_title: z.string().optional().describe('Title of the newspaper publication.'),
21
+ date: z.string().optional().describe('Issue publication date.'),
22
+ state: z.string().optional().describe('State where the newspaper was published.'),
23
+ edition: z.string().optional().describe('Edition or publication context identifier.'),
24
+ sequence: z.number().optional().describe('Page sequence number within the issue.'),
25
+ ocr_text: z
26
+ .string()
27
+ .describe('Full plain-text OCR content for the page. Empty string when ocr_available is false. May contain fragmented words, line-break artifacts, and misspellings inherent to historical OCR — do not attempt to repair.'),
28
+ ocr_available: z
29
+ .boolean()
30
+ .describe('True when digitized OCR text exists for this page. False for image-only digitization batches where OCR has not been applied.'),
31
+ }),
32
+ errors: [
33
+ {
34
+ reason: 'page_not_found',
35
+ code: JsonRpcErrorCode.NotFound,
36
+ when: 'The URL does not resolve to a valid LOC newspaper page resource.',
37
+ recovery: 'Re-run libofcongress_search_newspapers to get a fresh url from current results. Do not modify or guess page URLs.',
38
+ },
39
+ {
40
+ reason: 'rate_limit_exceeded',
41
+ code: JsonRpcErrorCode.ServiceUnavailable,
42
+ when: 'LOC API rate limit exceeded; requests are blocked for approximately 1 hour.',
43
+ recovery: 'Wait approximately 1 hour before retrying. Reduce request frequency to stay under 20 req/min.',
44
+ },
45
+ ],
46
+ handler(input, ctx) {
47
+ ctx.log.info('libofcongress_get_newspaper_page', { page_url: input.page_url });
48
+ // Validate before any outbound request: must be a well-formed URL on www.loc.gov/resource/
49
+ let parsed;
50
+ try {
51
+ parsed = new URL(input.page_url);
52
+ }
53
+ catch {
54
+ throw validationError('page_url must be a valid LOC newspaper page URL (e.g. https://www.loc.gov/resource/sn.../date/). Get it from a libofcongress_search_newspapers result.', { field: 'page_url' });
55
+ }
56
+ if (!input.page_url.startsWith(LOC_PAGE_URL_PREFIX)) {
57
+ throw validationError('page_url must begin with https://www.loc.gov/resource/. Pass the url field directly from a libofcongress_search_newspapers result.', { field: 'page_url', received: `${parsed.origin}${parsed.pathname}` });
58
+ }
59
+ const svc = getLocApiService();
60
+ return svc.getNewspaperPage(input.page_url, ctx);
61
+ },
62
+ format: (result) => {
63
+ const lines = [];
64
+ if (result.newspaper_title)
65
+ lines.push(`# ${result.newspaper_title}`);
66
+ lines.push(`**URL:** ${result.page_url}`);
67
+ if (result.date)
68
+ lines.push(`**Date:** ${result.date}`);
69
+ if (result.state)
70
+ lines.push(`**State:** ${result.state}`);
71
+ if (result.edition)
72
+ lines.push(`**Edition:** ${result.edition}`);
73
+ if (result.sequence !== undefined)
74
+ lines.push(`**Sequence:** ${result.sequence}`);
75
+ lines.push(`**OCR available:** ${result.ocr_available ? 'Yes' : 'No'}`);
76
+ if (result.ocr_available && result.ocr_text) {
77
+ lines.push('\n---\n');
78
+ lines.push(result.ocr_text);
79
+ }
80
+ else if (result.ocr_available && !result.ocr_text) {
81
+ lines.push('\n_OCR is digitized for this page but the text could not be retrieved._');
82
+ }
83
+ else {
84
+ lines.push('\n_No digitized OCR text available for this page (image-only digitization batch)._');
85
+ }
86
+ return [{ type: 'text', text: lines.join('\n') }];
87
+ },
88
+ });
89
+ //# sourceMappingURL=libofcongress-get-newspaper-page.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libofcongress-get-newspaper-page.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/libofcongress-get-newspaper-page.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @fileoverview libofcongress_search_newspapers tool — search historical newspaper pages in the Chronicling America corpus.
3
+ * @module mcp-server/tools/definitions/libofcongress-search-newspapers.tool
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ export declare const locSearchNewspapers: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ query: z.ZodString;
9
+ date_start: z.ZodOptional<z.ZodNumber>;
10
+ date_end: z.ZodOptional<z.ZodNumber>;
11
+ state: z.ZodOptional<z.ZodString>;
12
+ newspaper_title: z.ZodOptional<z.ZodString>;
13
+ limit: z.ZodDefault<z.ZodNumber>;
14
+ page: z.ZodDefault<z.ZodNumber>;
15
+ }, z.core.$strip>, z.ZodObject<{
16
+ items: z.ZodArray<z.ZodObject<{
17
+ url: z.ZodString;
18
+ title: z.ZodString;
19
+ description: z.ZodOptional<z.ZodString>;
20
+ date: z.ZodOptional<z.ZodString>;
21
+ state: z.ZodOptional<z.ZodString>;
22
+ newspaper_title: z.ZodOptional<z.ZodString>;
23
+ }, z.core.$strip>>;
24
+ total: z.ZodNumber;
25
+ page: z.ZodNumber;
26
+ pages: z.ZodNumber;
27
+ has_next: z.ZodBoolean;
28
+ message: z.ZodOptional<z.ZodString>;
29
+ }, z.core.$strip>, readonly [{
30
+ readonly reason: "empty_results";
31
+ readonly code: JsonRpcErrorCode.NotFound;
32
+ readonly when: "No newspaper pages matched the query and filters.";
33
+ readonly recovery: "Broaden the date range, remove the state filter, or try different keywords. OCR search is approximate — spelling variations in historical text are common.";
34
+ }, {
35
+ readonly reason: "rate_limit_exceeded";
36
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
37
+ readonly when: "LOC API rate limit exceeded; requests are blocked for approximately 1 hour.";
38
+ readonly recovery: "Wait approximately 1 hour before retrying. Reduce request frequency to stay under 20 req/min.";
39
+ }]>;
40
+ //# sourceMappingURL=libofcongress-search-newspapers.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libofcongress-search-newspapers.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/libofcongress-search-newspapers.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAmB,MAAM,+BAA+B,CAAC;AAGlF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmL9B,CAAC"}
@@ -0,0 +1,162 @@
1
+ /**
2
+ * @fileoverview libofcongress_search_newspapers tool — search historical newspaper pages in the Chronicling America corpus.
3
+ * @module mcp-server/tools/definitions/libofcongress-search-newspapers.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 locSearchNewspapers = tool('libofcongress_search_newspapers', {
9
+ title: 'Search Historical Newspapers',
10
+ description: 'Search historical newspaper pages in the Chronicling America corpus. Returns matching pages with OCR text excerpts (~500 characters), publication title, date, state, and the page URL needed for libofcongress_get_newspaper_page. Filters by keyword, date range, US state, and newspaper title. The OCR excerpts are sufficient for relevance assessment — call libofcongress_get_newspaper_page with the returned url field to read the full page text. OCR quality varies: 19th-century and degraded materials may contain fragmented or garbled text.',
11
+ annotations: { readOnlyHint: true, openWorldHint: true },
12
+ input: z.object({
13
+ query: z.string().min(1).describe('Keyword search across OCR text and newspaper metadata.'),
14
+ date_start: z
15
+ .number()
16
+ .int()
17
+ .optional()
18
+ .describe('Start year for date filter, inclusive (e.g., 1900). Omit for no lower bound.'),
19
+ date_end: z
20
+ .number()
21
+ .int()
22
+ .optional()
23
+ .describe('End year for date filter, inclusive (e.g., 1920). Omit for no upper bound.'),
24
+ state: z
25
+ .string()
26
+ .optional()
27
+ .describe('Filter to newspapers published in this US state. Use the full state name, lowercase (e.g., "oklahoma", "new york").'),
28
+ newspaper_title: z
29
+ .string()
30
+ .optional()
31
+ .describe('Filter to a specific newspaper by title (partial match accepted).'),
32
+ limit: z
33
+ .number()
34
+ .int()
35
+ .min(1)
36
+ .max(100)
37
+ .default(25)
38
+ .describe('Results per page. Default 25, max 100.'),
39
+ page: z
40
+ .number()
41
+ .int()
42
+ .min(1)
43
+ .default(1)
44
+ .describe('1-indexed page number for paginating results.'),
45
+ }),
46
+ output: z.object({
47
+ items: z
48
+ .array(z
49
+ .object({
50
+ url: z
51
+ .string()
52
+ .describe('LOC resource URL for this page — pass to libofcongress_get_newspaper_page to get full OCR text.'),
53
+ title: z.string().describe('Page or issue title.'),
54
+ description: z
55
+ .string()
56
+ .optional()
57
+ .describe('OCR text excerpt (~500 chars) for relevance assessment.'),
58
+ date: z.string().optional().describe('Issue publication date.'),
59
+ state: z.string().optional().describe('State where the newspaper was published.'),
60
+ newspaper_title: z.string().optional().describe('Newspaper publication title.'),
61
+ })
62
+ .describe('A single newspaper page search result.'))
63
+ .describe('Newspaper page results matching the search query and filters.'),
64
+ total: z.number().describe('Total number of matching newspaper pages in the result set.'),
65
+ page: z.number().describe('Current 1-indexed page number.'),
66
+ pages: z.number().describe('Total number of pages available.'),
67
+ has_next: z.boolean().describe('True when more pages are available after this one.'),
68
+ message: z
69
+ .string()
70
+ .optional()
71
+ .describe('Recovery hint when results are empty — echoes the applied filters and suggests how to broaden. Absent on non-empty result pages.'),
72
+ }),
73
+ errors: [
74
+ {
75
+ reason: 'empty_results',
76
+ code: JsonRpcErrorCode.NotFound,
77
+ when: 'No newspaper pages matched the query and filters.',
78
+ recovery: 'Broaden the date range, remove the state filter, or try different keywords. OCR search is approximate — spelling variations in historical text are common.',
79
+ },
80
+ {
81
+ reason: 'rate_limit_exceeded',
82
+ code: JsonRpcErrorCode.ServiceUnavailable,
83
+ when: 'LOC API rate limit exceeded; requests are blocked for approximately 1 hour.',
84
+ recovery: 'Wait approximately 1 hour before retrying. Reduce request frequency to stay under 20 req/min.',
85
+ },
86
+ ],
87
+ async handler(input, ctx) {
88
+ ctx.log.info('libofcongress_search_newspapers', {
89
+ query: input.query,
90
+ state: input.state,
91
+ page: input.page,
92
+ });
93
+ if (input.date_start !== undefined &&
94
+ input.date_end !== undefined &&
95
+ input.date_start > input.date_end) {
96
+ 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 });
97
+ }
98
+ const svc = getLocApiService();
99
+ const result = await svc.searchNewspapers({
100
+ query: input.query,
101
+ ...(input.date_start !== undefined && { dateStart: input.date_start }),
102
+ ...(input.date_end !== undefined && { dateEnd: input.date_end }),
103
+ ...(input.state?.trim() && { state: input.state.trim() }),
104
+ ...(input.newspaper_title?.trim() && { newspaperTitle: input.newspaper_title.trim() }),
105
+ limit: input.limit,
106
+ page: input.page,
107
+ }, ctx);
108
+ if (result.items.length === 0) {
109
+ return {
110
+ items: [],
111
+ total: 0,
112
+ page: input.page,
113
+ pages: 0,
114
+ has_next: false,
115
+ message: `No newspaper pages matched "${input.query}"` +
116
+ (input.state ? ` in state "${input.state}"` : '') +
117
+ (input.date_start || input.date_end
118
+ ? ` in dates ${input.date_start ?? ''}–${input.date_end ?? ''}`
119
+ : '') +
120
+ '. Try broadening the date range, removing the state filter, or using different keywords. Historical OCR is approximate — variant spellings are common.',
121
+ };
122
+ }
123
+ const { total, page, pages, hasNext } = result.pagination;
124
+ if (pages > 0 && page > pages) {
125
+ return {
126
+ items: [],
127
+ total,
128
+ page,
129
+ pages,
130
+ has_next: false,
131
+ message: `No results on page ${page} — query has ${pages} page(s) total (${total} items). Use a page number between 1 and ${pages}.`,
132
+ };
133
+ }
134
+ return {
135
+ items: result.items,
136
+ total,
137
+ page,
138
+ pages,
139
+ has_next: hasNext,
140
+ };
141
+ },
142
+ format: (result) => {
143
+ const lines = [];
144
+ lines.push(`**Total:** ${result.total} | **Page:** ${result.page} of ${result.pages} | **has_next:** ${result.has_next}`);
145
+ if (result.message)
146
+ lines.push(`\n> ${result.message}`);
147
+ for (const item of result.items) {
148
+ lines.push(`\n## ${item.title}`);
149
+ if (item.newspaper_title)
150
+ lines.push(`**Publication:** ${item.newspaper_title}`);
151
+ if (item.date)
152
+ lines.push(`**Date:** ${item.date}`);
153
+ if (item.state)
154
+ lines.push(`**State:** ${item.state}`);
155
+ if (item.description)
156
+ lines.push(item.description);
157
+ lines.push(`**URL:** ${item.url}`);
158
+ }
159
+ return [{ type: 'text', text: lines.join('\n') }];
160
+ },
161
+ });
162
+ //# sourceMappingURL=libofcongress-search-newspapers.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libofcongress-search-newspapers.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/libofcongress-search-newspapers.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @fileoverview libofcongress_search_subjects tool — search Library of Congress Subject Headings (LCSH).
3
+ * @module mcp-server/tools/definitions/libofcongress-search-subjects.tool
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ export declare const locSearchSubjects: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ query: z.ZodString;
9
+ limit: z.ZodDefault<z.ZodNumber>;
10
+ }, z.core.$strip>, z.ZodObject<{
11
+ subjects: z.ZodArray<z.ZodObject<{
12
+ label: z.ZodString;
13
+ uri: z.ZodString;
14
+ count: z.ZodOptional<z.ZodNumber>;
15
+ }, z.core.$strip>>;
16
+ total: z.ZodNumber;
17
+ message: z.ZodOptional<z.ZodString>;
18
+ }, z.core.$strip>, readonly [{
19
+ readonly reason: "empty_results";
20
+ readonly code: JsonRpcErrorCode.NotFound;
21
+ readonly when: "No LCSH headings matched the query.";
22
+ readonly recovery: "Try broader or different terms. LCSH uses inverted forms for many headings (e.g., \"Photography, Aerial\" not \"Aerial photography\").";
23
+ }]>;
24
+ //# sourceMappingURL=libofcongress-search-subjects.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libofcongress-search-subjects.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/libofcongress-search-subjects.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;GA4F5B,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * @fileoverview libofcongress_search_subjects tool — search Library of Congress Subject Headings (LCSH).
3
+ * @module mcp-server/tools/definitions/libofcongress-search-subjects.tool
4
+ */
5
+ import { tool, z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getLcLinkedDataService } from '../../../services/lc-linked-data/lc-linked-data-service.js';
8
+ export const locSearchSubjects = tool('libofcongress_search_subjects', {
9
+ title: 'Search LC Subject Headings',
10
+ description: 'Search Library of Congress Subject Headings (LCSH) by keyword. Returns controlled-vocabulary subject labels and their URIs. Use the returned label as the subject filter in libofcongress_search — LCSH uses precise, standardized terms that differ from natural language (e.g., "World War, 1939-1945" not "World War II"; "Photography, Aerial" not "Aerial photography"). Running this tool before a subject-filtered libofcongress_search dramatically improves result quality.',
11
+ annotations: { readOnlyHint: true, openWorldHint: true },
12
+ input: z.object({
13
+ query: z
14
+ .string()
15
+ .min(1)
16
+ .describe('Keyword or partial subject heading to search for (e.g., "civil war", "immigration", "jazz").'),
17
+ limit: z
18
+ .number()
19
+ .int()
20
+ .min(1)
21
+ .max(50)
22
+ .default(10)
23
+ .describe('Maximum number of subject headings to return. Default 10, max 50.'),
24
+ }),
25
+ output: z.object({
26
+ subjects: z
27
+ .array(z
28
+ .object({
29
+ label: z
30
+ .string()
31
+ .describe('Standardized LCSH heading — use this exact string in the libofcongress_search subject filter.'),
32
+ uri: z
33
+ .string()
34
+ .describe('Stable LOC URI identifying this subject heading in the authority file.'),
35
+ count: z
36
+ .number()
37
+ .optional()
38
+ .describe('Approximate number of LOC items carrying this heading. Omitted when unavailable.'),
39
+ })
40
+ .describe('A single LCSH subject heading record.'))
41
+ .describe('LCSH subject headings matching the query, ordered by relevance.'),
42
+ total: z.number().describe('Number of subject headings returned.'),
43
+ message: z
44
+ .string()
45
+ .optional()
46
+ .describe('Recovery hint when results are empty — suggests alternative search strategies. Absent on non-empty result pages.'),
47
+ }),
48
+ errors: [
49
+ {
50
+ reason: 'empty_results',
51
+ code: JsonRpcErrorCode.NotFound,
52
+ when: 'No LCSH headings matched the query.',
53
+ recovery: 'Try broader or different terms. LCSH uses inverted forms for many headings (e.g., "Photography, Aerial" not "Aerial photography").',
54
+ },
55
+ ],
56
+ async handler(input, ctx) {
57
+ ctx.log.info('libofcongress_search_subjects', { query: input.query, limit: input.limit });
58
+ const svc = getLcLinkedDataService();
59
+ const subjects = await svc.searchSubjects(input.query, input.limit, ctx);
60
+ if (subjects.length === 0) {
61
+ return {
62
+ subjects: [],
63
+ total: 0,
64
+ message: `No LCSH headings matched "${input.query}". Try broader or different terms. LCSH uses inverted forms for many headings — for example, "Photography, Aerial" instead of "Aerial photography", or "World War, 1939-1945" instead of "World War II".`,
65
+ };
66
+ }
67
+ return {
68
+ subjects,
69
+ total: subjects.length,
70
+ };
71
+ },
72
+ format: (result) => {
73
+ const lines = [];
74
+ lines.push(`**${result.total} subject heading(s) found**`);
75
+ if (result.message)
76
+ lines.push(`\n> ${result.message}`);
77
+ for (const s of result.subjects) {
78
+ lines.push(`\n## ${s.label}`);
79
+ lines.push(`**URI:** ${s.uri}`);
80
+ if (s.count !== undefined)
81
+ lines.push(`**Items:** ${s.count}`);
82
+ }
83
+ return [{ type: 'text', text: lines.join('\n') }];
84
+ },
85
+ });
86
+ //# sourceMappingURL=libofcongress-search-subjects.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libofcongress-search-subjects.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/libofcongress-search-subjects.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qDAAqD,CAAC;AAE7F,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,+BAA+B,EAAE;IACrE,KAAK,EAAE,4BAA4B;IACnC,WAAW,EACT,sdAAsd;IACxd,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IACxD,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CACP,8FAA8F,CAC/F;QACH,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,EAAE,CAAC;aACP,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CAAC,mEAAmE,CAAC;KACjF,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,QAAQ,EAAE,CAAC;aACR,KAAK,CACJ,CAAC;aACE,MAAM,CAAC;YACN,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,CACP,+FAA+F,CAChG;YACH,GAAG,EAAE,CAAC;iBACH,MAAM,EAAE;iBACR,QAAQ,CAAC,wEAAwE,CAAC;YACrF,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACP,kFAAkF,CACnF;SACJ,CAAC;aACD,QAAQ,CAAC,uCAAuC,CAAC,CACrD;aACA,QAAQ,CAAC,iEAAiE,CAAC;QAC9E,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;QAClE,OAAO,EAAE,CAAC;aACP,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,kHAAkH,CACnH;KACJ,CAAC;IAEF,MAAM,EAAE;QACN;YACE,MAAM,EAAE,eAAe;YACvB,IAAI,EAAE,gBAAgB,CAAC,QAAQ;YAC/B,IAAI,EAAE,qCAAqC;YAC3C,QAAQ,EACN,oIAAoI;SACvI;KACF;IAED,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,+BAA+B,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1F,MAAM,GAAG,GAAG,sBAAsB,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAEzE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO;gBACL,QAAQ,EAAE,EAAE;gBACZ,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,6BAA6B,KAAK,CAAC,KAAK,0MAA0M;aAC5P,CAAC;QACJ,CAAC;QAED,OAAO;YACL,QAAQ;YACR,KAAK,EAAE,QAAQ,CAAC,MAAM;SACvB,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACjB,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,KAAK,6BAA6B,CAAC,CAAC;QAC3D,IAAI,MAAM,CAAC,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QACxD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;YAChC,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS;gBAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @fileoverview libofcongress_search tool — search Library of Congress digital collections.
3
+ * @module mcp-server/tools/definitions/libofcongress-search.tool
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ export declare const locSearch: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ query: z.ZodString;
9
+ format: z.ZodOptional<z.ZodEnum<{
10
+ map: "map";
11
+ photo: "photo";
12
+ newspaper: "newspaper";
13
+ manuscript: "manuscript";
14
+ audio: "audio";
15
+ film: "film";
16
+ book: "book";
17
+ "notated-music": "notated-music";
18
+ }>>;
19
+ date_start: z.ZodOptional<z.ZodNumber>;
20
+ date_end: z.ZodOptional<z.ZodNumber>;
21
+ subject: z.ZodOptional<z.ZodString>;
22
+ location: z.ZodOptional<z.ZodString>;
23
+ limit: z.ZodDefault<z.ZodNumber>;
24
+ page: z.ZodDefault<z.ZodNumber>;
25
+ }, z.core.$strip>, z.ZodObject<{
26
+ items: z.ZodArray<z.ZodObject<{
27
+ id: z.ZodString;
28
+ title: z.ZodString;
29
+ date: z.ZodOptional<z.ZodString>;
30
+ description: z.ZodOptional<z.ZodString>;
31
+ format: z.ZodOptional<z.ZodString>;
32
+ url: z.ZodString;
33
+ }, z.core.$strip>>;
34
+ total: z.ZodNumber;
35
+ page: z.ZodNumber;
36
+ pages: z.ZodNumber;
37
+ has_next: z.ZodBoolean;
38
+ message: z.ZodOptional<z.ZodString>;
39
+ }, z.core.$strip>, readonly [{
40
+ readonly reason: "empty_results";
41
+ readonly code: JsonRpcErrorCode.NotFound;
42
+ readonly when: "No items matched the query and filters.";
43
+ readonly recovery: "Broaden the query, widen the date range, or use libofcongress_search_subjects to find the correct subject heading spelling.";
44
+ }, {
45
+ readonly reason: "rate_limit_exceeded";
46
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
47
+ readonly when: "LOC API rate limit exceeded; requests are blocked for approximately 1 hour.";
48
+ readonly recovery: "Wait approximately 1 hour before retrying. Reduce request frequency to stay under 20 req/min.";
49
+ }]>;
50
+ //# sourceMappingURL=libofcongress-search.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libofcongress-search.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/libofcongress-search.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAmB,MAAM,+BAA+B,CAAC;AAGlF,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+LpB,CAAC"}