@cyanheads/ris-austria-mcp-server 0.1.5

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 (154) hide show
  1. package/AGENTS.md +401 -0
  2. package/CLAUDE.md +401 -0
  3. package/Dockerfile +125 -0
  4. package/LICENSE +201 -0
  5. package/README.md +309 -0
  6. package/changelog/0.1.x/0.1.0.md +25 -0
  7. package/changelog/0.1.x/0.1.1.md +24 -0
  8. package/changelog/0.1.x/0.1.2.md +16 -0
  9. package/changelog/0.1.x/0.1.3.md +11 -0
  10. package/changelog/0.1.x/0.1.4.md +11 -0
  11. package/changelog/0.1.x/0.1.5.md +18 -0
  12. package/changelog/template.md +129 -0
  13. package/dist/config/server-config.d.ts +19 -0
  14. package/dist/config/server-config.d.ts.map +1 -0
  15. package/dist/config/server-config.js +35 -0
  16. package/dist/config/server-config.js.map +1 -0
  17. package/dist/index.d.ts +7 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +37 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/mcp-server/resources/definitions/ris-document.resource.d.ts +30 -0
  22. package/dist/mcp-server/resources/definitions/ris-document.resource.d.ts.map +1 -0
  23. package/dist/mcp-server/resources/definitions/ris-document.resource.js +75 -0
  24. package/dist/mcp-server/resources/definitions/ris-document.resource.js.map +1 -0
  25. package/dist/mcp-server/tools/definitions/_shared.d.ts +8 -0
  26. package/dist/mcp-server/tools/definitions/_shared.d.ts.map +1 -0
  27. package/dist/mcp-server/tools/definitions/_shared.js +10 -0
  28. package/dist/mcp-server/tools/definitions/_shared.js.map +1 -0
  29. package/dist/mcp-server/tools/definitions/ris-get-document.tool.d.ts +189 -0
  30. package/dist/mcp-server/tools/definitions/ris-get-document.tool.d.ts.map +1 -0
  31. package/dist/mcp-server/tools/definitions/ris-get-document.tool.js +504 -0
  32. package/dist/mcp-server/tools/definitions/ris-get-document.tool.js.map +1 -0
  33. package/dist/mcp-server/tools/definitions/ris-list-reference.tool.d.ts +42 -0
  34. package/dist/mcp-server/tools/definitions/ris-list-reference.tool.d.ts.map +1 -0
  35. package/dist/mcp-server/tools/definitions/ris-list-reference.tool.js +316 -0
  36. package/dist/mcp-server/tools/definitions/ris-list-reference.tool.js.map +1 -0
  37. package/dist/mcp-server/tools/definitions/ris-lookup-citation.tool.d.ts +80 -0
  38. package/dist/mcp-server/tools/definitions/ris-lookup-citation.tool.d.ts.map +1 -0
  39. package/dist/mcp-server/tools/definitions/ris-lookup-citation.tool.js +529 -0
  40. package/dist/mcp-server/tools/definitions/ris-lookup-citation.tool.js.map +1 -0
  41. package/dist/mcp-server/tools/definitions/ris-search-announcements.tool.d.ts +118 -0
  42. package/dist/mcp-server/tools/definitions/ris-search-announcements.tool.d.ts.map +1 -0
  43. package/dist/mcp-server/tools/definitions/ris-search-announcements.tool.js +389 -0
  44. package/dist/mcp-server/tools/definitions/ris-search-announcements.tool.js.map +1 -0
  45. package/dist/mcp-server/tools/definitions/ris-search-case-law.tool.d.ts +178 -0
  46. package/dist/mcp-server/tools/definitions/ris-search-case-law.tool.d.ts.map +1 -0
  47. package/dist/mcp-server/tools/definitions/ris-search-case-law.tool.js +495 -0
  48. package/dist/mcp-server/tools/definitions/ris-search-case-law.tool.js.map +1 -0
  49. package/dist/mcp-server/tools/definitions/ris-search-drafts.tool.d.ts +80 -0
  50. package/dist/mcp-server/tools/definitions/ris-search-drafts.tool.d.ts.map +1 -0
  51. package/dist/mcp-server/tools/definitions/ris-search-drafts.tool.js +264 -0
  52. package/dist/mcp-server/tools/definitions/ris-search-drafts.tool.js.map +1 -0
  53. package/dist/mcp-server/tools/definitions/ris-search-gazette.tool.d.ts +147 -0
  54. package/dist/mcp-server/tools/definitions/ris-search-gazette.tool.d.ts.map +1 -0
  55. package/dist/mcp-server/tools/definitions/ris-search-gazette.tool.js +509 -0
  56. package/dist/mcp-server/tools/definitions/ris-search-gazette.tool.js.map +1 -0
  57. package/dist/mcp-server/tools/definitions/ris-search-legislation.tool.d.ts +145 -0
  58. package/dist/mcp-server/tools/definitions/ris-search-legislation.tool.d.ts.map +1 -0
  59. package/dist/mcp-server/tools/definitions/ris-search-legislation.tool.js +466 -0
  60. package/dist/mcp-server/tools/definitions/ris-search-legislation.tool.js.map +1 -0
  61. package/dist/mcp-server/tools/definitions/ris-track-changes.tool.d.ts +73 -0
  62. package/dist/mcp-server/tools/definitions/ris-track-changes.tool.d.ts.map +1 -0
  63. package/dist/mcp-server/tools/definitions/ris-track-changes.tool.js +265 -0
  64. package/dist/mcp-server/tools/definitions/ris-track-changes.tool.js.map +1 -0
  65. package/dist/services/ris/normalizer.d.ts +40 -0
  66. package/dist/services/ris/normalizer.d.ts.map +1 -0
  67. package/dist/services/ris/normalizer.js +480 -0
  68. package/dist/services/ris/normalizer.js.map +1 -0
  69. package/dist/services/ris/reference/applications.d.ts +529 -0
  70. package/dist/services/ris/reference/applications.d.ts.map +1 -0
  71. package/dist/services/ris/reference/applications.js +520 -0
  72. package/dist/services/ris/reference/applications.js.map +1 -0
  73. package/dist/services/ris/reference/changed-since-intervals.d.ts +42 -0
  74. package/dist/services/ris/reference/changed-since-intervals.d.ts.map +1 -0
  75. package/dist/services/ris/reference/changed-since-intervals.js +16 -0
  76. package/dist/services/ris/reference/changed-since-intervals.js.map +1 -0
  77. package/dist/services/ris/reference/citation-formats.d.ts +39 -0
  78. package/dist/services/ris/reference/citation-formats.d.ts.map +1 -0
  79. package/dist/services/ris/reference/citation-formats.js +39 -0
  80. package/dist/services/ris/reference/citation-formats.js.map +1 -0
  81. package/dist/services/ris/reference/collections.d.ts +82 -0
  82. package/dist/services/ris/reference/collections.d.ts.map +1 -0
  83. package/dist/services/ris/reference/collections.js +102 -0
  84. package/dist/services/ris/reference/collections.js.map +1 -0
  85. package/dist/services/ris/reference/courts.d.ts +201 -0
  86. package/dist/services/ris/reference/courts.d.ts.map +1 -0
  87. package/dist/services/ris/reference/courts.js +198 -0
  88. package/dist/services/ris/reference/courts.js.map +1 -0
  89. package/dist/services/ris/reference/decision-kinds.d.ts +78 -0
  90. package/dist/services/ris/reference/decision-kinds.d.ts.map +1 -0
  91. package/dist/services/ris/reference/decision-kinds.js +117 -0
  92. package/dist/services/ris/reference/decision-kinds.js.map +1 -0
  93. package/dist/services/ris/reference/decision-types.d.ts +36 -0
  94. package/dist/services/ris/reference/decision-types.d.ts.map +1 -0
  95. package/dist/services/ris/reference/decision-types.js +29 -0
  96. package/dist/services/ris/reference/decision-types.js.map +1 -0
  97. package/dist/services/ris/reference/district-authorities.d.ts +314 -0
  98. package/dist/services/ris/reference/district-authorities.d.ts.map +1 -0
  99. package/dist/services/ris/reference/district-authorities.js +212 -0
  100. package/dist/services/ris/reference/district-authorities.js.map +1 -0
  101. package/dist/services/ris/reference/gazette-parts.d.ts +73 -0
  102. package/dist/services/ris/reference/gazette-parts.d.ts.map +1 -0
  103. package/dist/services/ris/reference/gazette-parts.js +58 -0
  104. package/dist/services/ris/reference/gazette-parts.js.map +1 -0
  105. package/dist/services/ris/reference/index.d.ts +23 -0
  106. package/dist/services/ris/reference/index.d.ts.map +1 -0
  107. package/dist/services/ris/reference/index.js +23 -0
  108. package/dist/services/ris/reference/index.js.map +1 -0
  109. package/dist/services/ris/reference/issuing-bodies.d.ts +642 -0
  110. package/dist/services/ris/reference/issuing-bodies.d.ts.map +1 -0
  111. package/dist/services/ris/reference/issuing-bodies.js +616 -0
  112. package/dist/services/ris/reference/issuing-bodies.js.map +1 -0
  113. package/dist/services/ris/reference/justiz-subject-areas.d.ts +133 -0
  114. package/dist/services/ris/reference/justiz-subject-areas.d.ts.map +1 -0
  115. package/dist/services/ris/reference/justiz-subject-areas.js +67 -0
  116. package/dist/services/ris/reference/justiz-subject-areas.js.map +1 -0
  117. package/dist/services/ris/reference/law-types.d.ts +46 -0
  118. package/dist/services/ris/reference/law-types.d.ts.map +1 -0
  119. package/dist/services/ris/reference/law-types.js +41 -0
  120. package/dist/services/ris/reference/law-types.js.map +1 -0
  121. package/dist/services/ris/reference/ministries.d.ts +360 -0
  122. package/dist/services/ris/reference/ministries.d.ts.map +1 -0
  123. package/dist/services/ris/reference/ministries.js +408 -0
  124. package/dist/services/ris/reference/ministries.js.map +1 -0
  125. package/dist/services/ris/reference/search-syntax.d.ts +66 -0
  126. package/dist/services/ris/reference/search-syntax.d.ts.map +1 -0
  127. package/dist/services/ris/reference/search-syntax.js +65 -0
  128. package/dist/services/ris/reference/search-syntax.js.map +1 -0
  129. package/dist/services/ris/reference/section-types.d.ts +33 -0
  130. package/dist/services/ris/reference/section-types.d.ts.map +1 -0
  131. package/dist/services/ris/reference/section-types.js +29 -0
  132. package/dist/services/ris/reference/section-types.js.map +1 -0
  133. package/dist/services/ris/reference/stages.d.ts +41 -0
  134. package/dist/services/ris/reference/stages.d.ts.map +1 -0
  135. package/dist/services/ris/reference/stages.js +27 -0
  136. package/dist/services/ris/reference/stages.js.map +1 -0
  137. package/dist/services/ris/reference/states.d.ts +90 -0
  138. package/dist/services/ris/reference/states.d.ts.map +1 -0
  139. package/dist/services/ris/reference/states.js +85 -0
  140. package/dist/services/ris/reference/states.js.map +1 -0
  141. package/dist/services/ris/request-builder.d.ts +195 -0
  142. package/dist/services/ris/request-builder.d.ts.map +1 -0
  143. package/dist/services/ris/request-builder.js +673 -0
  144. package/dist/services/ris/request-builder.js.map +1 -0
  145. package/dist/services/ris/ris-service.d.ts +65 -0
  146. package/dist/services/ris/ris-service.d.ts.map +1 -0
  147. package/dist/services/ris/ris-service.js +200 -0
  148. package/dist/services/ris/ris-service.js.map +1 -0
  149. package/dist/services/ris/types.d.ts +651 -0
  150. package/dist/services/ris/types.d.ts.map +1 -0
  151. package/dist/services/ris/types.js +11 -0
  152. package/dist/services/ris/types.js.map +1 -0
  153. package/package.json +108 -0
  154. package/server.json +111 -0
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @fileoverview ris_track_changes — the precise, deletion-aware change feed over RIS's
3
+ * History controller: every document added or changed in one application within an exact
4
+ * date window, optionally including deletions. The delta-sync and monitoring primitive the
5
+ * coarse, additive-only `changed_since` (ImRisSeit) intervals cannot express. History
6
+ * responses reuse the standard normalized envelope, so each changed document surfaces in a
7
+ * cross-class record shape (identity, label, dates, binding, renditions) plus `changed`;
8
+ * removed documents surface as `deleted` records. The service maps the four History
9
+ * application-name aliases (BrKons→Bundesnormen, LrKons→Landesnormen, Gr→Gemeinderecht,
10
+ * GrA→GemeinderechtAuth) internally.
11
+ * @module mcp-server/tools/definitions/ris-track-changes
12
+ */
13
+ import { z } from '@cyanheads/mcp-ts-core';
14
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
15
+ export declare const risTrackChanges: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
16
+ application: z.ZodEnum<{
17
+ [x: string]: string;
18
+ }>;
19
+ changed_from: z.ZodOptional<z.ZodString>;
20
+ changed_to: z.ZodOptional<z.ZodString>;
21
+ include_deleted: z.ZodOptional<z.ZodBoolean>;
22
+ page: z.ZodOptional<z.ZodNumber>;
23
+ page_size: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<10>, z.ZodLiteral<20>, z.ZodLiteral<50>, z.ZodLiteral<100>]>>;
24
+ }, z.core.$strip>, z.ZodObject<{
25
+ results: z.ZodArray<z.ZodObject<{
26
+ document_number: z.ZodString;
27
+ title: z.ZodOptional<z.ZodString>;
28
+ short_title: z.ZodOptional<z.ZodString>;
29
+ organ: z.ZodOptional<z.ZodString>;
30
+ changed: z.ZodOptional<z.ZodString>;
31
+ published: z.ZodOptional<z.ZodString>;
32
+ document_url: z.ZodOptional<z.ZodString>;
33
+ binding_status: z.ZodEnum<{
34
+ translation: "translation";
35
+ authentic: "authentic";
36
+ consolidated_informational: "consolidated_informational";
37
+ historical_record: "historical_record";
38
+ decision: "decision";
39
+ preparatory: "preparatory";
40
+ administrative_directive: "administrative_directive";
41
+ }>;
42
+ deleted: z.ZodBoolean;
43
+ deleted_at: z.ZodOptional<z.ZodString>;
44
+ content_urls: z.ZodObject<{
45
+ xml: z.ZodOptional<z.ZodString>;
46
+ html: z.ZodOptional<z.ZodString>;
47
+ pdf: z.ZodOptional<z.ZodString>;
48
+ rtf: z.ZodOptional<z.ZodString>;
49
+ }, z.core.$strip>;
50
+ authentic_pdf_url: z.ZodOptional<z.ZodString>;
51
+ }, z.core.$strip>>;
52
+ }, z.core.$strip>, readonly [{
53
+ readonly reason: "invalid_query";
54
+ readonly code: JsonRpcErrorCode.ValidationError;
55
+ readonly when: "RIS rejected a parameter value — the in-band Client error message is passed through verbatim; it names the invalid element and its valid values (e.g. an application History does not carry).";
56
+ readonly recovery: "Correct the parameter RIS names in the message. Ground valid application codes with ris_list_reference topic applications.";
57
+ }, {
58
+ readonly reason: "upstream_error";
59
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
60
+ readonly when: "RIS is unreachable, returned a server error, or served an HTML error page.";
61
+ readonly retryable: true;
62
+ readonly recovery: "RIS is temporarily unavailable — retry after a short delay. If it persists, reduce page_size or narrow the window.";
63
+ }], {
64
+ readonly totalCount: z.ZodNumber;
65
+ readonly page: z.ZodNumber;
66
+ readonly pageSize: z.ZodNumber;
67
+ readonly truncated: z.ZodOptional<z.ZodBoolean>;
68
+ readonly application: z.ZodString;
69
+ readonly changedFrom: z.ZodOptional<z.ZodString>;
70
+ readonly changedTo: z.ZodOptional<z.ZodString>;
71
+ readonly notice: z.ZodOptional<z.ZodString>;
72
+ }>;
73
+ //# sourceMappingURL=ris-track-changes.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ris-track-changes.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/ris-track-changes.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAiI3E,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkK1B,CAAC"}
@@ -0,0 +1,265 @@
1
+ /**
2
+ * @fileoverview ris_track_changes — the precise, deletion-aware change feed over RIS's
3
+ * History controller: every document added or changed in one application within an exact
4
+ * date window, optionally including deletions. The delta-sync and monitoring primitive the
5
+ * coarse, additive-only `changed_since` (ImRisSeit) intervals cannot express. History
6
+ * responses reuse the standard normalized envelope, so each changed document surfaces in a
7
+ * cross-class record shape (identity, label, dates, binding, renditions) plus `changed`;
8
+ * removed documents surface as `deleted` records. The service maps the four History
9
+ * application-name aliases (BrKons→Bundesnormen, LrKons→Landesnormen, Gr→Gemeinderecht,
10
+ * GrA→GemeinderechtAuth) internally.
11
+ * @module mcp-server/tools/definitions/ris-track-changes
12
+ */
13
+ import { tool, z } from '@cyanheads/mcp-ts-core';
14
+ import { JsonRpcErrorCode, McpError } from '@cyanheads/mcp-ts-core/errors';
15
+ import { RIS_APPLICATIONS } from '../../../services/ris/reference/index.js';
16
+ import { getRisService } from '../../../services/ris/ris-service.js';
17
+ import { isoDateString } from './_shared.js';
18
+ const APPLICATION_CODES = RIS_APPLICATIONS.map((app) => app.code);
19
+ const APPLICATION_BY_CODE = new Map(RIS_APPLICATIONS.map((app) => [app.code, app]));
20
+ const BINDING_STATUSES = [
21
+ 'authentic',
22
+ 'consolidated_informational',
23
+ 'historical_record',
24
+ 'decision',
25
+ 'preparatory',
26
+ 'administrative_directive',
27
+ 'translation',
28
+ ];
29
+ /** Map an empty string from a form-based client to `undefined`. */
30
+ function meaningful(value) {
31
+ return value !== undefined && value !== '' ? value : undefined;
32
+ }
33
+ const ContentUrlsSchema = z
34
+ .object({
35
+ xml: z.string().optional().describe('XML rendition URL (RIS Nutzdaten schema).'),
36
+ html: z.string().optional().describe('HTML rendition URL.'),
37
+ pdf: z.string().optional().describe('PDF rendition URL.'),
38
+ rtf: z.string().optional().describe('RTF rendition URL.'),
39
+ })
40
+ .describe('Rendition URLs of the changed document. Empty for a deletion record.');
41
+ const ChangeRecordSchema = z
42
+ .object({
43
+ document_number: z
44
+ .string()
45
+ .describe('Technical RIS document number (Technisch.ID) — pass with application to ris_get_document.'),
46
+ title: z.string().optional().describe('Document title, HTML markup stripped, where present.'),
47
+ short_title: z.string().optional().describe('Short title (Kurztitel), where assigned.'),
48
+ organ: z
49
+ .string()
50
+ .optional()
51
+ .describe('Issuing body (Organ) of the document, where the record carries one.'),
52
+ changed: z
53
+ .string()
54
+ .optional()
55
+ .describe('Date this document last changed in RIS (Allgemein.Geaendert).'),
56
+ published: z
57
+ .string()
58
+ .optional()
59
+ .describe('Date this document was first published in RIS (Allgemein.Veroeffentlicht).'),
60
+ document_url: z
61
+ .string()
62
+ .optional()
63
+ .describe('RIS web view of the document (Allgemein.DokumentUrl) — for humans.'),
64
+ binding_status: z
65
+ .enum(BINDING_STATUSES)
66
+ .describe('Legal binding status of the queried application — authentic (amtssigniert, legally binding), consolidated_informational, historical_record, decision, preparatory, administrative_directive, or translation.'),
67
+ deleted: z
68
+ .boolean()
69
+ .describe('True when this record marks a document removed from RIS (include_deleted only).'),
70
+ deleted_at: z
71
+ .string()
72
+ .optional()
73
+ .describe('Deletion import timestamp (ImportTimestamp) — deletion records only.'),
74
+ content_urls: ContentUrlsSchema,
75
+ authentic_pdf_url: z
76
+ .string()
77
+ .optional()
78
+ .describe('The amtssigniert authentic PDF (.pdfsig, Authentisch DataType), where the changed document publishes one.'),
79
+ })
80
+ .describe('One change-feed entry — a changed document, or a deletion record.');
81
+ /** Map a normalized History change to the tool's record shape. */
82
+ function toRecord(change, bindingStatus) {
83
+ if (change.kind === 'deleted') {
84
+ const { deletedAt, documentNumber, organ } = change.record;
85
+ return {
86
+ binding_status: bindingStatus,
87
+ content_urls: {},
88
+ deleted: true,
89
+ document_number: documentNumber,
90
+ ...(deletedAt !== undefined && { deleted_at: deletedAt }),
91
+ ...(organ !== undefined && { organ }),
92
+ };
93
+ }
94
+ const { hit } = change;
95
+ const md = hit.metadata;
96
+ const title = md.title;
97
+ const shortTitle = 'shortTitle' in md ? md.shortTitle : undefined;
98
+ const { html, pdf, rtf, xml } = hit.contentUrls;
99
+ return {
100
+ binding_status: bindingStatus,
101
+ content_urls: {
102
+ ...(xml !== undefined && { xml }),
103
+ ...(html !== undefined && { html }),
104
+ ...(pdf !== undefined && { pdf }),
105
+ ...(rtf !== undefined && { rtf }),
106
+ },
107
+ deleted: false,
108
+ document_number: hit.documentNumber,
109
+ ...(hit.contentUrls.authentic !== undefined && {
110
+ authentic_pdf_url: hit.contentUrls.authentic,
111
+ }),
112
+ ...(hit.changed !== undefined && { changed: hit.changed }),
113
+ ...(hit.documentUrl !== undefined && { document_url: hit.documentUrl }),
114
+ ...(hit.organ !== undefined && { organ: hit.organ }),
115
+ ...(hit.published !== undefined && { published: hit.published }),
116
+ ...(shortTitle !== undefined && { short_title: shortTitle }),
117
+ ...(title !== undefined && { title }),
118
+ };
119
+ }
120
+ export const risTrackChanges = tool('ris_track_changes', {
121
+ title: 'Track RIS Changes',
122
+ description: 'Track every document added or changed in one RIS application within an exact date window (changed_from/changed_to) via the History controller, optionally including deletions (include_deleted) — the delta-sync and monitoring primitive for mirrors and watchers, and the only surface that reports removals. Unlike the search tools’ coarse, additive-only changed_since intervals, this is exact-dated and deletion-aware. application takes any RIS application code (e.g. BrKons, Dsk, BgblAuth); the four History name aliases are handled internally. Each changed document comes back in a compact cross-class record — document_number (for ris_get_document), title, dates, binding_status, and rendition URLs — plus its last-changed date; removed documents come back as deleted records with a deletion timestamp. One application per call; page explicitly for large windows. Application codes and coverage: ris_list_reference topic applications.',
123
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
124
+ input: z.object({
125
+ application: z
126
+ .enum(APPLICATION_CODES)
127
+ .describe('RIS application whose change feed to read (standard code, e.g. BrKons, LrKons, Dsk, BgblAuth). History’s four aliased names are mapped internally. Codes: ris_list_reference topic applications.'),
128
+ changed_from: isoDateString
129
+ .optional()
130
+ .describe('Include documents changed on/after this date (YYYY-MM-DD, AenderungenVon). Exact date, not a coarse interval.'),
131
+ changed_to: isoDateString
132
+ .optional()
133
+ .describe('Include documents changed on/before this date (YYYY-MM-DD, AenderungenBis).'),
134
+ include_deleted: z
135
+ .boolean()
136
+ .optional()
137
+ .describe('true also returns documents removed from RIS in the window, as deleted records — the only way to observe deletions.'),
138
+ page: z.number().int().min(1).optional().describe('1-based result page. Default 1.'),
139
+ page_size: z
140
+ .union([z.literal(10), z.literal(20), z.literal(50), z.literal(100)])
141
+ .optional()
142
+ .describe('Documents per page — RIS accepts 10, 20, 50, or 100. Default 20.'),
143
+ }),
144
+ output: z.object({
145
+ results: z
146
+ .array(ChangeRecordSchema)
147
+ .describe('Change-feed entries for the requested page. Totals, paging, and the applied window in enrichment.'),
148
+ }),
149
+ enrichment: {
150
+ totalCount: z.number().describe('Total change-feed entries across all pages.'),
151
+ page: z.number().describe('1-based page number RIS served.'),
152
+ pageSize: z.number().describe('Page size RIS applied.'),
153
+ truncated: z
154
+ .boolean()
155
+ .optional()
156
+ .describe('Present and true when more pages exist beyond this one — raise page to continue.'),
157
+ application: z.string().describe('The application whose change feed was read.'),
158
+ changedFrom: z
159
+ .string()
160
+ .optional()
161
+ .describe('The changed_from bound the server applied (echo), when set.'),
162
+ changedTo: z
163
+ .string()
164
+ .optional()
165
+ .describe('The changed_to bound the server applied (echo), when set.'),
166
+ notice: z
167
+ .string()
168
+ .optional()
169
+ .describe('Zero-hit guidance — names the likely cause and the concrete next call.'),
170
+ },
171
+ errors: [
172
+ {
173
+ reason: 'invalid_query',
174
+ code: JsonRpcErrorCode.ValidationError,
175
+ when: 'RIS rejected a parameter value — the in-band Client error message is passed through verbatim; it names the invalid element and its valid values (e.g. an application History does not carry).',
176
+ recovery: 'Correct the parameter RIS names in the message. Ground valid application codes with ris_list_reference topic applications.',
177
+ },
178
+ {
179
+ reason: 'upstream_error',
180
+ code: JsonRpcErrorCode.ServiceUnavailable,
181
+ when: 'RIS is unreachable, returned a server error, or served an HTML error page.',
182
+ retryable: true,
183
+ recovery: 'RIS is temporarily unavailable — retry after a short delay. If it persists, reduce page_size or narrow the window.',
184
+ },
185
+ ],
186
+ async handler(input, ctx) {
187
+ const changedFrom = meaningful(input.changed_from);
188
+ const changedTo = meaningful(input.changed_to);
189
+ // application is a Zod enum of the reference codes, so the lookup always resolves.
190
+ const bindingStatus = APPLICATION_BY_CODE.get(input.application).binding;
191
+ const params = {
192
+ application: input.application,
193
+ ...(changedFrom !== undefined && { changedFrom }),
194
+ ...(changedTo !== undefined && { changedTo }),
195
+ ...(input.include_deleted === true && { includeDeleted: true }),
196
+ ...(input.page !== undefined && { page: input.page }),
197
+ ...(input.page_size !== undefined && { pageSize: input.page_size }),
198
+ };
199
+ // Map in-band RIS errors onto this tool's declared contract so reason +
200
+ // recovery reach the wire (service-level throws carry neither).
201
+ const result = await getRisService()
202
+ .trackChanges(params, ctx)
203
+ .catch((err) => {
204
+ if (err instanceof McpError && err.code === JsonRpcErrorCode.InvalidParams) {
205
+ throw ctx.fail('invalid_query', err.message, { ...ctx.recoveryFor('invalid_query') });
206
+ }
207
+ if (err instanceof McpError && err.code === JsonRpcErrorCode.ServiceUnavailable) {
208
+ throw ctx.fail('upstream_error', err.message, { ...ctx.recoveryFor('upstream_error') });
209
+ }
210
+ throw err;
211
+ });
212
+ ctx.log.info('Change feed read', {
213
+ application: input.application,
214
+ entries: result.changes.length,
215
+ total: result.total,
216
+ });
217
+ ctx.enrich.total(result.total);
218
+ ctx.enrich({ application: input.application, page: result.page, pageSize: result.pageSize });
219
+ if (changedFrom !== undefined)
220
+ ctx.enrich({ changedFrom });
221
+ if (changedTo !== undefined)
222
+ ctx.enrich({ changedTo });
223
+ if (result.total > (result.page - 1) * result.pageSize + result.changes.length) {
224
+ ctx.enrich({ truncated: true });
225
+ }
226
+ if (result.total === 0) {
227
+ ctx.enrich.notice(`0 changes in ${input.application} between ${changedFrom ?? 'the start of the feed'} and ${changedTo ?? 'now'}. Windows are exact dates — widen the range, or use the search tools' changed_since for coarse recency filtering.`);
228
+ }
229
+ return { results: result.changes.map((change) => toRecord(change, bindingStatus)) };
230
+ },
231
+ // format() populates content[] — the markdown twin of structuredContent. Every output
232
+ // field renders here; totals, paging, and the applied window ride the enrichment trailer.
233
+ format: (result) => {
234
+ if (result.results.length === 0) {
235
+ return [{ type: 'text', text: '_No changes on this page._' }];
236
+ }
237
+ const blocks = result.results.map((r) => {
238
+ const lines = [
239
+ `## ${r.title ?? r.short_title ?? r.document_number}${r.deleted ? ' — deleted' : ''}`,
240
+ `**Document:** ${r.document_number}`,
241
+ ];
242
+ if (r.short_title !== undefined)
243
+ lines.push(`**Short title:** ${r.short_title}`);
244
+ if (r.organ !== undefined)
245
+ lines.push(`**Organ:** ${r.organ}`);
246
+ lines.push(`**Binding:** ${r.binding_status}`);
247
+ if (r.changed !== undefined || r.published !== undefined) {
248
+ lines.push(`**Changed:** ${r.changed ?? 'unknown'}${r.published !== undefined ? ` | **Published:** ${r.published}` : ''}`);
249
+ }
250
+ lines.push(`**Deleted:** ${r.deleted ? `yes${r.deleted_at !== undefined ? ` (${r.deleted_at})` : ''}` : 'no'}`);
251
+ if (r.document_url !== undefined)
252
+ lines.push(`**RIS view:** ${r.document_url}`);
253
+ if (r.authentic_pdf_url !== undefined)
254
+ lines.push(`**Authentic PDF:** ${r.authentic_pdf_url}`);
255
+ const urls = ['html', 'pdf', 'rtf', 'xml']
256
+ .filter((key) => r.content_urls[key] !== undefined)
257
+ .map((key) => `[${key.toUpperCase()}](${r.content_urls[key]})`);
258
+ if (urls.length > 0)
259
+ lines.push(`**Text:** ${urls.join(' · ')}`);
260
+ return lines.join('\n');
261
+ });
262
+ return [{ type: 'text', text: blocks.join('\n\n') }];
263
+ },
264
+ });
265
+ //# sourceMappingURL=ris-track-changes.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ris-track-changes.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/ris-track-changes.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @fileoverview Normalizer for RIS OGD responses: unwraps the JSON-serialized-XML envelope,
3
+ * coerces object-or-array lists, classifies in-band errors, and maps the six controller
4
+ * metadata classes to the normalized shapes in `types.ts`.
5
+ *
6
+ * Error classification (observed live 2026-07-05): the handbook documents an `@type`
7
+ * attribute on `OgdSearchResult.Error`, but production responses omit it and prefix the
8
+ * message with `soap:Client.` / `soap:Server.` instead — both signals are checked. Client
9
+ * errors become `InvalidParams` with RIS's message passed through (it names the invalid
10
+ * element); everything else is treated as a transient upstream failure, never a
11
+ * `SerializationError`.
12
+ * @module services/ris/normalizer
13
+ */
14
+ import type { OneOrMany, RawDocumentReference, RawOgdSearchResult, RawWrappedList, RisChangeSet, RisHit, RisSearchResult } from './types.js';
15
+ /** Coerce RIS's object-or-array serialization to an array (empty for null/undefined/''). */
16
+ export declare function coerceOneOrMany<T>(value: OneOrMany<T> | '' | undefined): T[];
17
+ /**
18
+ * Coerce a RIS wrapped list (`{ item: T | T[] }`), a bare scalar, or an empty element to
19
+ * a string array — the upstream uses all three shapes for the same logical field.
20
+ */
21
+ export declare function coerceWrappedList(value: RawWrappedList<string> | string | '' | undefined): string[];
22
+ /** Strip `<br/>` markers and residual HTML remnants from RIS text fields. */
23
+ export declare function stripHtmlRemnants(text: string): string;
24
+ /** Parse `[CELEX-Nr.: …]` markers (possibly multi-valued) out of RIS text fields. */
25
+ export declare function parseCelexReferences(...texts: (string | undefined)[]): string[];
26
+ /** Detect an HTML error page masquerading as an API response. */
27
+ export declare function isHtmlErrorPage(text: string): boolean;
28
+ /**
29
+ * Throw when the envelope carries an in-band error. Client errors pass RIS's message
30
+ * through — it names the invalid element and its expected datatype; Server and
31
+ * unclassifiable errors are transient (`ServiceUnavailable`).
32
+ */
33
+ export declare function assertNoInBandError(result: RawOgdSearchResult): void;
34
+ /** Parse a search-controller response into a normalized result page. */
35
+ export declare function parseSearchResponse(payload: unknown): RisSearchResult;
36
+ /** Parse a History-controller response, separating changed documents from deletions. */
37
+ export declare function parseHistoryResponse(payload: unknown): RisChangeSet;
38
+ /** Normalize one search hit. Throws `ServiceUnavailable` on unrecognized hit shapes. */
39
+ export declare function normalizeHit(ref: RawDocumentReference): RisHit;
40
+ //# sourceMappingURL=normalizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizer.d.ts","sourceRoot":"","sources":["../../../src/services/ris/normalizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EACV,SAAS,EAKT,oBAAoB,EAQpB,kBAAkB,EAGlB,cAAc,EAId,YAAY,EAIZ,MAAM,EAKN,eAAe,EAEhB,MAAM,YAAY,CAAC;AAMpB,4FAA4F;AAC5F,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,CAAC,EAAE,CAG5E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,EAAE,GAAG,SAAS,GACtD,MAAM,EAAE,CAMV;AAWD,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQtD;AAgBD,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,GAAG,KAAK,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,CAW/E;AAED,iEAAiE;AACjE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAwBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CASpE;AAiCD,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,CAGrE;AAED,wFAAwF;AACxF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAoBnE;AAiTD,wFAAwF;AACxF,wBAAgB,YAAY,CAAC,GAAG,EAAE,oBAAoB,GAAG,MAAM,CA8B9D"}