@cyanheads/eur-lex-mcp-server 0.1.8 → 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/AGENTS.md +1 -1
- package/CLAUDE.md +1 -1
- package/README.md +1 -1
- package/changelog/0.2.x/0.2.0.md +22 -0
- package/dist/mcp-server/tools/definitions/eurlex-browse-subjects.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-browse-subjects.tool.js +12 -0
- package/dist/mcp-server/tools/definitions/eurlex-browse-subjects.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-get-document.tool.d.ts +8 -3
- package/dist/mcp-server/tools/definitions/eurlex-get-document.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-get-document.tool.js +43 -7
- package/dist/mcp-server/tools/definitions/eurlex-get-document.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-get-relations.tool.d.ts +9 -4
- package/dist/mcp-server/tools/definitions/eurlex-get-relations.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-get-relations.tool.js +56 -21
- package/dist/mcp-server/tools/definitions/eurlex-get-relations.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-lookup-celex.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-lookup-celex.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-lookup-celex.tool.js +16 -60
- package/dist/mcp-server/tools/definitions/eurlex-lookup-celex.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/index.d.ts +18 -8
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
- package/dist/services/cellar-sparql/eli-resolution.d.ts +45 -0
- package/dist/services/cellar-sparql/eli-resolution.d.ts.map +1 -0
- package/dist/services/cellar-sparql/eli-resolution.js +71 -0
- package/dist/services/cellar-sparql/eli-resolution.js.map +1 -0
- package/package.json +1 -1
- package/server.json +3 -3
package/AGENTS.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** eur-lex-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
4
|
+
**Version:** 0.2.0
|
|
5
5
|
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.10.9`
|
|
6
6
|
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
7
|
**MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
|
package/CLAUDE.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** eur-lex-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
4
|
+
**Version:** 0.2.0
|
|
5
5
|
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.10.9`
|
|
6
6
|
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
7
|
**MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/eur-lex-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/eur-lex-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "eurlex_get_document accepts eli_uri and eurlex_get_relations accepts work_uri as functional identifier alternatives (exactly one of the pair required); eurlex_browse_subjects restricts results to EuroVoc concepts so every concept_uri is usable as an eurovoc_concept filter"
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.2.0 — 2026-06-30
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **`eli_uri` on `eurlex_get_document`** ([#8](https://github.com/cyanheads/eur-lex-mcp-server/issues/8)) — accepts a work-level ELI URI (e.g. `http://data.europa.eu/eli/reg/2016/679`, with or without `/oj`) as an alternative to `celex_number`, resolved to its CELLAR work by an exact `cdm:resource_legal_eli` match with a bare-work `/oj` retry. The resolution is now shared with `eurlex_lookup_celex` via the new `services/cellar-sparql/eli-resolution.ts`.
|
|
12
|
+
- **`work_uri` on `eurlex_get_relations`** ([#8](https://github.com/cyanheads/eur-lex-mcp-server/issues/8)) — accepts a CELLAR work resource URI used directly to seed the relation traversal, skipping the CELEX→work resolution step.
|
|
13
|
+
|
|
14
|
+
## Changed
|
|
15
|
+
|
|
16
|
+
- **`celex_number` is now optional** on `eurlex_get_document` and `eurlex_get_relations` ([#8](https://github.com/cyanheads/eur-lex-mcp-server/issues/8)) — each call takes exactly one of its identifier pair. Passing neither or both raises a new `invalid_identifier_args` (`ValidationError`), and an empty-string field from form-based clients is treated as absent. Existing `celex_number`-only calls are unaffected.
|
|
17
|
+
- **`eurlex_get_relations` output** ([#8](https://github.com/cyanheads/eur-lex-mcp-server/issues/8)) — `work_uri` is now always present; `celex_number` is now optional, omitted when the work was addressed directly by `work_uri`.
|
|
18
|
+
|
|
19
|
+
## Fixed
|
|
20
|
+
|
|
21
|
+
- **Advertised URI alternatives were unreachable** ([#8](https://github.com/cyanheads/eur-lex-mcp-server/issues/8)) — `eli_uri` (`eurlex_get_document`) and `work_uri` (`eurlex_get_relations`) were documented as alternatives, but a required `celex_number` meant they could never be supplied alone. Both now resolve.
|
|
22
|
+
- **`eurlex_browse_subjects` returned unusable URIs** ([#11](https://github.com/cyanheads/eur-lex-mcp-server/issues/11)) — a `STRSTARTS` filter limits results to the `http://eurovoc.europa.eu/` namespace, so every returned `concept_uri` works in the `eurlex_search_documents` `eurovoc_concept` filter. Other Publications Office authority concepts (e.g. `class-sum-leg`, `fd_*`), which that filter cannot match, are no longer returned.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eurlex-browse-subjects.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-browse-subjects.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"eurlex-browse-subjects.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-browse-subjects.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAgBjE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;cAqIjC,CAAC"}
|
|
@@ -5,11 +5,22 @@
|
|
|
5
5
|
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
6
|
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
import { CellarSparqlService, getCellarSparqlService, } from '../../../services/cellar-sparql/cellar-sparql-service.js';
|
|
8
|
+
/**
|
|
9
|
+
* Namespace of actual EuroVoc concepts. CELLAR's skos:Concept space also holds
|
|
10
|
+
* other Publications Office authority concepts (class-sum-leg, fd_*, …) whose
|
|
11
|
+
* URIs the eurlex_search_documents `eurovoc_concept` filter accepts but cannot
|
|
12
|
+
* match — only `http://eurovoc.europa.eu/` concepts are bound by
|
|
13
|
+
* `cdm:work_is_about_concept_eurovoc`. Results are restricted to this namespace
|
|
14
|
+
* so every URI returned is usable in that filter (#11).
|
|
15
|
+
*/
|
|
16
|
+
const EUROVOC_CONCEPT_NAMESPACE = 'http://eurovoc.europa.eu/';
|
|
8
17
|
export const eurlex_browse_subjects = tool('eurlex_browse_subjects', {
|
|
9
18
|
title: 'Browse EuroVoc Subjects',
|
|
10
19
|
description: 'Search the EuroVoc multilingual thesaurus to resolve a human-readable term or keyword into EuroVoc concept IDs. ' +
|
|
11
20
|
'This tool is required before using the eurovoc_concept filter in eurlex_search_documents — ' +
|
|
12
21
|
'agents cannot guess numeric EuroVoc concept IDs. ' +
|
|
22
|
+
'Every returned concept_uri is a EuroVoc concept (http://eurovoc.europa.eu/…) directly usable in that filter; ' +
|
|
23
|
+
'other Publications Office authority concepts are excluded because the filter cannot match them. ' +
|
|
13
24
|
'Returns concept URI, preferred label in the requested language, concept code, and broader/narrower hierarchy hints. ' +
|
|
14
25
|
'EuroVoc covers all EU policy domains: agriculture, environment, finance, health, trade, transport, and more. ' +
|
|
15
26
|
'If no results are found in a non-English language, retry with language "en" and a broader English term.',
|
|
@@ -75,6 +86,7 @@ SELECT ?concept ?label ?code ?broaderLabel WHERE {
|
|
|
75
86
|
?broader skos:prefLabel ?broaderLabel .
|
|
76
87
|
FILTER(LANG(?broaderLabel) = "${lang}")
|
|
77
88
|
}
|
|
89
|
+
FILTER(STRSTARTS(STR(?concept), "${EUROVOC_CONCEPT_NAMESPACE}"))
|
|
78
90
|
FILTER(LANG(?label) = "${lang}")
|
|
79
91
|
FILTER(CONTAINS(LCASE(STR(?label)), "${keyword.replace(/"/g, '\\"')}"))
|
|
80
92
|
} LIMIT ${limit}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eurlex-browse-subjects.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-browse-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,EACL,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mDAAmD,CAAC;AAE3D,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC,wBAAwB,EAAE;IACnE,KAAK,EAAE,yBAAyB;IAChC,WAAW,EACT,kHAAkH;QAClH,6FAA6F;QAC7F,mDAAmD;QACnD,sHAAsH;QACtH,+GAA+G;QAC/G,yGAAyG;IAC3G,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE;IAC9E,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,OAAO,EAAE,CAAC;aACP,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CACP,+FAA+F,CAChG;QACH,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,KAAK,CAAC,cAAc,CAAC;aACrB,OAAO,CAAC,IAAI,CAAC;aACb,QAAQ,CAAC,gFAAgF,CAAC;QAC7F,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,sEAAsE,CAAC;KACpF,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,QAAQ,EAAE,CAAC;aACR,KAAK,CACJ,CAAC;aACE,MAAM,CAAC;YACN,WAAW,EAAE,CAAC;iBACX,MAAM,EAAE;iBACR,QAAQ,CAAC,yEAAyE,CAAC;YACtF,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,QAAQ,CAAC,4DAA4D,CAAC;YACzE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YAC7E,aAAa,EAAE,CAAC;iBACb,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,gEAAgE,CAAC;SAC9E,CAAC;aACD,QAAQ,CAAC,4EAA4E,CAAC,CAC1F;aACA,QAAQ,CAAC,oEAAoE,CAAC;QACjF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;KAC5E,CAAC;IAEF,MAAM,EAAE;QACN;YACE,MAAM,EAAE,aAAa;YACrB,IAAI,EAAE,gBAAgB,CAAC,QAAQ;YAC/B,IAAI,EAAE,oEAAoE;YAC1E,QAAQ,EAAE,gFAAgF;SAC3F;KACF;IAED,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,MAAM,GAAG,GAAG,sBAAsB,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QACnD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;QACzD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAE1B,MAAM,MAAM,GAAG;;;;;;;;oCAQiB,IAAI;;
|
|
1
|
+
{"version":3,"file":"eurlex-browse-subjects.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-browse-subjects.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
6
|
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
export declare const eurlex_get_document: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
|
|
8
|
-
celex_number: z.ZodString
|
|
8
|
+
celex_number: z.ZodOptional<z.ZodString>;
|
|
9
9
|
eli_uri: z.ZodOptional<z.ZodString>;
|
|
10
10
|
language: z.ZodDefault<z.ZodString>;
|
|
11
11
|
format: z.ZodDefault<z.ZodEnum<{
|
|
@@ -28,10 +28,15 @@ export declare const eurlex_get_document: import("@cyanheads/mcp-ts-core").ToolD
|
|
|
28
28
|
language_fallback: z.ZodOptional<z.ZodString>;
|
|
29
29
|
content_format: z.ZodString;
|
|
30
30
|
}, z.core.$strip>, readonly [{
|
|
31
|
+
readonly reason: "invalid_identifier_args";
|
|
32
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
33
|
+
readonly when: "Neither celex_number nor eli_uri was provided, or both were.";
|
|
34
|
+
readonly recovery: "Provide exactly one of celex_number or eli_uri.";
|
|
35
|
+
}, {
|
|
31
36
|
readonly reason: "not_found";
|
|
32
37
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
33
|
-
readonly when: "CELEX number not found in CELLAR — the work does not exist in the corpus.";
|
|
34
|
-
readonly recovery: "Verify the
|
|
38
|
+
readonly when: "CELEX number or ELI URI not found in CELLAR — the work does not exist in the corpus.";
|
|
39
|
+
readonly recovery: "Verify the identifier or use eurlex_lookup_celex to confirm it exists.";
|
|
35
40
|
}, {
|
|
36
41
|
readonly reason: "language_unavailable";
|
|
37
42
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eurlex-get-document.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-get-document.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"eurlex-get-document.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-get-document.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAiBjE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAgS9B,CAAC"}
|
|
@@ -6,6 +6,7 @@ import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
|
6
6
|
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
import { ENG_LANGUAGE_URI, resolveCorporateBodyLabel, resolveResourceTypeLabel, } from '../../../services/cellar-sparql/cdm-labels.js';
|
|
8
8
|
import { CellarSparqlService, getCellarSparqlService, } from '../../../services/cellar-sparql/cellar-sparql-service.js';
|
|
9
|
+
import { escapeSparqlLiteral, resolveEliToWork } from '../../../services/cellar-sparql/eli-resolution.js';
|
|
9
10
|
import { getEurLexContentService, } from '../../../services/eurlex-content/eurlex-content-service.js';
|
|
10
11
|
export const eurlex_get_document = tool('eurlex_get_document', {
|
|
11
12
|
title: 'Get EU Document',
|
|
@@ -22,12 +23,15 @@ export const eurlex_get_document = tool('eurlex_get_document', {
|
|
|
22
23
|
input: z.object({
|
|
23
24
|
celex_number: z
|
|
24
25
|
.string()
|
|
25
|
-
.
|
|
26
|
-
.describe('CELEX number of the act to fetch (e.g. 32016R0679 for GDPR).
|
|
26
|
+
.optional()
|
|
27
|
+
.describe('CELEX number of the act to fetch (e.g. 32016R0679 for GDPR). ' +
|
|
28
|
+
'Provide exactly one of celex_number or eli_uri.'),
|
|
27
29
|
eli_uri: z
|
|
28
30
|
.string()
|
|
29
31
|
.optional()
|
|
30
|
-
.describe('ELI URI
|
|
32
|
+
.describe('Work-level ELI URI of the act to fetch, resolved to its CELLAR work (e.g. ' +
|
|
33
|
+
'http://data.europa.eu/eli/reg/2016/679, with or without the /oj suffix). ' +
|
|
34
|
+
'Provide exactly one of celex_number or eli_uri.'),
|
|
31
35
|
language: z
|
|
32
36
|
.string()
|
|
33
37
|
.regex(/^[A-Za-z]{2,3}$/)
|
|
@@ -77,11 +81,17 @@ export const eurlex_get_document = tool('eurlex_get_document', {
|
|
|
77
81
|
content_format: z.string().describe('Format of the returned content: "html" or "xml".'),
|
|
78
82
|
}),
|
|
79
83
|
errors: [
|
|
84
|
+
{
|
|
85
|
+
reason: 'invalid_identifier_args',
|
|
86
|
+
code: JsonRpcErrorCode.ValidationError,
|
|
87
|
+
when: 'Neither celex_number nor eli_uri was provided, or both were.',
|
|
88
|
+
recovery: 'Provide exactly one of celex_number or eli_uri.',
|
|
89
|
+
},
|
|
80
90
|
{
|
|
81
91
|
reason: 'not_found',
|
|
82
92
|
code: JsonRpcErrorCode.NotFound,
|
|
83
|
-
when: 'CELEX number not found in CELLAR — the work does not exist in the corpus.',
|
|
84
|
-
recovery: 'Verify the
|
|
93
|
+
when: 'CELEX number or ELI URI not found in CELLAR — the work does not exist in the corpus.',
|
|
94
|
+
recovery: 'Verify the identifier or use eurlex_lookup_celex to confirm it exists.',
|
|
85
95
|
},
|
|
86
96
|
{
|
|
87
97
|
reason: 'language_unavailable',
|
|
@@ -99,10 +109,36 @@ export const eurlex_get_document = tool('eurlex_get_document', {
|
|
|
99
109
|
async handler(input, ctx) {
|
|
100
110
|
const sparqlSvc = getCellarSparqlService();
|
|
101
111
|
const contentSvc = getEurLexContentService();
|
|
102
|
-
|
|
112
|
+
// Accept exactly one identifier: a CELEX number, or an ELI URI resolved to
|
|
113
|
+
// its CELLAR work. Treat empty/whitespace as absent so form-based clients
|
|
114
|
+
// that send "" for an omitted field route to the friendly guard, not -32602.
|
|
115
|
+
// An ELI is resolved to its CELLAR work via the shared #5 resolution
|
|
116
|
+
// (cdm:resource_legal_eli exact-match + bare-work /oj retry), then the rest
|
|
117
|
+
// of the flow (metadata + content) is keyed on the confirmed CELEX.
|
|
118
|
+
const celexInput = input.celex_number?.trim();
|
|
119
|
+
const eliInput = input.eli_uri?.trim();
|
|
120
|
+
let celexNumber;
|
|
121
|
+
if (eliInput && !celexInput) {
|
|
122
|
+
const binding = await resolveEliToWork(sparqlSvc, eliInput, ctx);
|
|
123
|
+
const resolvedCelex = binding && CellarSparqlService.bindingValue(binding, 'celexNumber');
|
|
124
|
+
if (!resolvedCelex) {
|
|
125
|
+
throw ctx.fail('not_found', `No CELLAR work found for ELI: ${eliInput}`, {
|
|
126
|
+
...ctx.recoveryFor('not_found'),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
celexNumber = resolvedCelex;
|
|
130
|
+
}
|
|
131
|
+
else if (celexInput && !eliInput) {
|
|
132
|
+
celexNumber = celexInput;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
throw ctx.fail('invalid_identifier_args', celexInput
|
|
136
|
+
? 'Provide only one of celex_number or eli_uri, not both.'
|
|
137
|
+
: 'Provide either celex_number or eli_uri.', { ...ctx.recoveryFor('invalid_identifier_args') });
|
|
138
|
+
}
|
|
103
139
|
const language = (input.language.trim().toUpperCase() || 'EN');
|
|
104
140
|
const format = input.format;
|
|
105
|
-
const safeCelexNumber = celexNumber
|
|
141
|
+
const safeCelexNumber = escapeSparqlLiteral(celexNumber);
|
|
106
142
|
// Step 1: Fetch metadata via SPARQL
|
|
107
143
|
const metaSparql = `
|
|
108
144
|
SELECT ?work ?celexNumber ?type ?date ?title ?inForce ?author ?legalBasis ?eurovoc WHERE {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eurlex-get-document.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-get-document.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,EACL,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mDAAmD,CAAC;AAC3D,OAAO,EAGL,uBAAuB,GACxB,MAAM,qDAAqD,CAAC;AAE7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC,qBAAqB,EAAE;IAC7D,KAAK,EAAE,iBAAiB;IACxB,WAAW,EACT,qFAAqF;QACrF,gHAAgH;QAChH,kEAAkE;QAClE,wFAAwF;QACxF,iDAAiD;QACjD,mHAAmH;QACnH,uEAAuE;QACvE,8EAA8E;QAC9E,4GAA4G;IAC9G,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IAC9E,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,YAAY,EAAE,CAAC;aACZ,MAAM,EAAE;aACR,
|
|
1
|
+
{"version":3,"file":"eurlex-get-document.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-get-document.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
6
|
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
export declare const eurlex_get_relations: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
|
|
8
|
-
celex_number: z.ZodString
|
|
8
|
+
celex_number: z.ZodOptional<z.ZodString>;
|
|
9
9
|
work_uri: z.ZodOptional<z.ZodString>;
|
|
10
10
|
relation_types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
11
11
|
cites: "cites";
|
|
@@ -15,8 +15,8 @@ export declare const eurlex_get_relations: import("@cyanheads/mcp-ts-core").Tool
|
|
|
15
15
|
consolidated_version: "consolidated_version";
|
|
16
16
|
}>>>;
|
|
17
17
|
}, z.core.$strip>, z.ZodObject<{
|
|
18
|
-
celex_number: z.ZodString
|
|
19
|
-
work_uri: z.
|
|
18
|
+
celex_number: z.ZodOptional<z.ZodString>;
|
|
19
|
+
work_uri: z.ZodString;
|
|
20
20
|
relations: z.ZodArray<z.ZodObject<{
|
|
21
21
|
relation_type: z.ZodString;
|
|
22
22
|
direction: z.ZodString;
|
|
@@ -25,9 +25,14 @@ export declare const eurlex_get_relations: import("@cyanheads/mcp-ts-core").Tool
|
|
|
25
25
|
}, z.core.$strip>>;
|
|
26
26
|
total: z.ZodNumber;
|
|
27
27
|
}, z.core.$strip>, readonly [{
|
|
28
|
+
readonly reason: "invalid_identifier_args";
|
|
29
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
30
|
+
readonly when: "Neither celex_number nor work_uri was provided, or both were.";
|
|
31
|
+
readonly recovery: "Provide exactly one of celex_number or work_uri.";
|
|
32
|
+
}, {
|
|
28
33
|
readonly reason: "not_found";
|
|
29
34
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
30
|
-
readonly when: "CELEX
|
|
35
|
+
readonly when: "CELEX number not found in CELLAR — resolve the identifier with eurlex_lookup_celex first.";
|
|
31
36
|
readonly recovery: "Use eurlex_lookup_celex to confirm the CELEX number exists, then retry.";
|
|
32
37
|
}, {
|
|
33
38
|
readonly reason: "no_relations";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eurlex-get-relations.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-get-relations.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"eurlex-get-relations.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-get-relations.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA4BjE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAkQ/B,CAAC"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
6
|
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
import { CellarSparqlService, getCellarSparqlService, } from '../../../services/cellar-sparql/cellar-sparql-service.js';
|
|
8
|
+
import { escapeSparqlLiteral } from '../../../services/cellar-sparql/eli-resolution.js';
|
|
8
9
|
/** CDM relation predicates traversed by this tool. */
|
|
9
10
|
const CDM_RELATIONS = {
|
|
10
11
|
cites: 'cdm:work_cites_work',
|
|
@@ -34,12 +35,21 @@ export const eurlex_get_relations = tool('eurlex_get_relations', {
|
|
|
34
35
|
input: z.object({
|
|
35
36
|
celex_number: z
|
|
36
37
|
.string()
|
|
37
|
-
.
|
|
38
|
-
.describe('CELEX number of the work to traverse (e.g. 32016R0679).
|
|
38
|
+
.optional()
|
|
39
|
+
.describe('CELEX number of the work to traverse (e.g. 32016R0679). ' +
|
|
40
|
+
'Provide exactly one of celex_number or work_uri.'),
|
|
39
41
|
work_uri: z
|
|
40
42
|
.string()
|
|
43
|
+
.refine((v) => !v ||
|
|
44
|
+
(v.startsWith('http') &&
|
|
45
|
+
!v.includes('>') &&
|
|
46
|
+
!v.includes('<') &&
|
|
47
|
+
!v.includes('"') &&
|
|
48
|
+
!v.includes(' ')), { message: 'work_uri must be a valid http URI with no angle brackets, quotes, or spaces.' })
|
|
41
49
|
.optional()
|
|
42
|
-
.describe('CELLAR work URI
|
|
50
|
+
.describe('CELLAR work resource URI to traverse (e.g. ' +
|
|
51
|
+
'http://publications.europa.eu/resource/cellar/3e485e15-11bd-11e6-ba9a-01aa75ed71a1). ' +
|
|
52
|
+
'Used directly without CELEX resolution. Provide exactly one of celex_number or work_uri.'),
|
|
43
53
|
relation_types: z
|
|
44
54
|
.array(z.enum(['cites', 'amends', 'amended_by', 'legal_basis', 'consolidated_version']))
|
|
45
55
|
.optional()
|
|
@@ -50,11 +60,12 @@ export const eurlex_get_relations = tool('eurlex_get_relations', {
|
|
|
50
60
|
output: z.object({
|
|
51
61
|
celex_number: z
|
|
52
62
|
.string()
|
|
53
|
-
.
|
|
63
|
+
.optional()
|
|
64
|
+
.describe('CELEX number of the source work whose relations were traversed. ' +
|
|
65
|
+
'Absent when the work was addressed directly by work_uri.'),
|
|
54
66
|
work_uri: z
|
|
55
67
|
.string()
|
|
56
|
-
.
|
|
57
|
-
.describe('CELLAR URI of the source work (resolved from the CELEX number).'),
|
|
68
|
+
.describe('CELLAR URI of the source work (the work_uri input, or resolved from the CELEX).'),
|
|
58
69
|
relations: z
|
|
59
70
|
.array(z
|
|
60
71
|
.object({
|
|
@@ -75,10 +86,16 @@ export const eurlex_get_relations = tool('eurlex_get_relations', {
|
|
|
75
86
|
total: z.number().describe('Total number of direct CDM relations returned.'),
|
|
76
87
|
}),
|
|
77
88
|
errors: [
|
|
89
|
+
{
|
|
90
|
+
reason: 'invalid_identifier_args',
|
|
91
|
+
code: JsonRpcErrorCode.ValidationError,
|
|
92
|
+
when: 'Neither celex_number nor work_uri was provided, or both were.',
|
|
93
|
+
recovery: 'Provide exactly one of celex_number or work_uri.',
|
|
94
|
+
},
|
|
78
95
|
{
|
|
79
96
|
reason: 'not_found',
|
|
80
97
|
code: JsonRpcErrorCode.NotFound,
|
|
81
|
-
when: 'CELEX
|
|
98
|
+
when: 'CELEX number not found in CELLAR — resolve the identifier with eurlex_lookup_celex first.',
|
|
82
99
|
recovery: 'Use eurlex_lookup_celex to confirm the CELEX number exists, then retry.',
|
|
83
100
|
},
|
|
84
101
|
{
|
|
@@ -90,21 +107,37 @@ export const eurlex_get_relations = tool('eurlex_get_relations', {
|
|
|
90
107
|
],
|
|
91
108
|
async handler(input, ctx) {
|
|
92
109
|
const svc = getCellarSparqlService();
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
110
|
+
// Accept exactly one identifier. Treat empty/whitespace as absent so
|
|
111
|
+
// form-based clients sending "" for an omitted field hit the friendly guard.
|
|
112
|
+
const celexNumber = input.celex_number?.trim();
|
|
113
|
+
const workUriInput = input.work_uri?.trim();
|
|
114
|
+
// Step 1: Determine the source work URI. A work_uri is the CELLAR work
|
|
115
|
+
// resource directly — use it as-is, skipping the CELEX→work resolution that
|
|
116
|
+
// would otherwise throw not_found before the URI could be used. A
|
|
117
|
+
// celex_number is resolved to its work first.
|
|
118
|
+
let workUri;
|
|
119
|
+
if (workUriInput && !celexNumber) {
|
|
120
|
+
workUri = workUriInput;
|
|
121
|
+
}
|
|
122
|
+
else if (celexNumber && !workUriInput) {
|
|
123
|
+
const resolveSparql = `
|
|
97
124
|
SELECT ?work WHERE {
|
|
98
125
|
?work cdm:resource_legal_id_celex ?celex .
|
|
99
|
-
FILTER(STR(?celex) = "${
|
|
126
|
+
FILTER(STR(?celex) = "${escapeSparqlLiteral(celexNumber)}")
|
|
100
127
|
} LIMIT 1`;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
128
|
+
const resolveBindings = await svc.query(resolveSparql, ctx);
|
|
129
|
+
if (resolveBindings.length === 0) {
|
|
130
|
+
throw ctx.fail('not_found', `No CELLAR work found for CELEX: ${celexNumber}`, {
|
|
131
|
+
...ctx.recoveryFor('not_found'),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
workUri = CellarSparqlService.bindingValue(resolveBindings[0], 'work') ?? '';
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
throw ctx.fail('invalid_identifier_args', celexNumber
|
|
138
|
+
? 'Provide only one of celex_number or work_uri, not both.'
|
|
139
|
+
: 'Provide either celex_number or work_uri.', { ...ctx.recoveryFor('invalid_identifier_args') });
|
|
106
140
|
}
|
|
107
|
-
const workUri = CellarSparqlService.bindingValue(resolveBindings[0], 'work') ?? input.work_uri ?? '';
|
|
108
141
|
// Step 2: Build relation type filter
|
|
109
142
|
const requestedTypes = input.relation_types ?? [
|
|
110
143
|
'cites',
|
|
@@ -143,7 +176,7 @@ SELECT ?relatedWork ?relatedCelex ?relationType ?direction WHERE {
|
|
|
143
176
|
resultCount: relationBindings.length,
|
|
144
177
|
});
|
|
145
178
|
if (relationBindings.length === 0) {
|
|
146
|
-
throw ctx.fail('no_relations', `Work ${celexNumber} has no CDM relations of the requested types.`, {
|
|
179
|
+
throw ctx.fail('no_relations', `Work ${celexNumber ?? workUri} has no CDM relations of the requested types.`, {
|
|
147
180
|
...ctx.recoveryFor('no_relations'),
|
|
148
181
|
});
|
|
149
182
|
}
|
|
@@ -170,14 +203,16 @@ SELECT ?relatedWork ?relatedCelex ?relationType ?direction WHERE {
|
|
|
170
203
|
relations.push(entry);
|
|
171
204
|
}
|
|
172
205
|
return {
|
|
173
|
-
celex_number: celexNumber,
|
|
206
|
+
...(celexNumber ? { celex_number: celexNumber } : {}),
|
|
174
207
|
work_uri: workUri,
|
|
175
208
|
relations,
|
|
176
209
|
total: relations.length,
|
|
177
210
|
};
|
|
178
211
|
},
|
|
179
212
|
format: (result) => {
|
|
180
|
-
const lines = [
|
|
213
|
+
const lines = [
|
|
214
|
+
`## Relations for ${result.celex_number ?? result.work_uri} (${result.total} found)\n`,
|
|
215
|
+
];
|
|
181
216
|
if (result.work_uri)
|
|
182
217
|
lines.push(`**Work URI:** ${result.work_uri}\n`);
|
|
183
218
|
const grouped = new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eurlex-get-relations.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-get-relations.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,EACL,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mDAAmD,CAAC;
|
|
1
|
+
{"version":3,"file":"eurlex-get-relations.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-get-relations.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,8 +8,8 @@ export declare const eurlex_lookup_celex: import("@cyanheads/mcp-ts-core").ToolD
|
|
|
8
8
|
identifier: z.ZodString;
|
|
9
9
|
identifier_type: z.ZodDefault<z.ZodEnum<{
|
|
10
10
|
auto: "auto";
|
|
11
|
-
celex: "celex";
|
|
12
11
|
eli: "eli";
|
|
12
|
+
celex: "celex";
|
|
13
13
|
}>>;
|
|
14
14
|
}, z.core.$strip>, z.ZodObject<{
|
|
15
15
|
found: z.ZodBoolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eurlex-lookup-celex.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-lookup-celex.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"eurlex-lookup-celex.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-lookup-celex.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAyBjE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;cA8H9B,CAAC"}
|
|
@@ -5,14 +5,11 @@
|
|
|
5
5
|
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
6
|
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
import { CellarSparqlService, getCellarSparqlService, } from '../../../services/cellar-sparql/cellar-sparql-service.js';
|
|
8
|
+
import { escapeSparqlLiteral, isEliUri, resolveEliToWork, } from '../../../services/cellar-sparql/eli-resolution.js';
|
|
8
9
|
/** Detect CELEX number format: starts with a sector digit. */
|
|
9
10
|
function isCelex(identifier) {
|
|
10
11
|
return /^[1-9]\d{4}[A-Z]+\d+/.test(identifier.trim());
|
|
11
12
|
}
|
|
12
|
-
/** Detect ELI URI format: starts with http://data.europa.eu/eli/ */
|
|
13
|
-
function isEliUri(identifier) {
|
|
14
|
-
return identifier.trim().startsWith('http://data.europa.eu/eli/');
|
|
15
|
-
}
|
|
16
13
|
function detectIdentifierType(identifier) {
|
|
17
14
|
if (isCelex(identifier))
|
|
18
15
|
return 'celex';
|
|
@@ -20,38 +17,6 @@ function detectIdentifierType(identifier) {
|
|
|
20
17
|
return 'eli';
|
|
21
18
|
return null;
|
|
22
19
|
}
|
|
23
|
-
const ELI_NAMESPACE = 'http://data.europa.eu/eli/';
|
|
24
|
-
/**
|
|
25
|
-
* A bare work-level ELI — `…/eli/{type}/{year}/{number}` with no manifestation
|
|
26
|
-
* suffix (no `/oj`, no `/YYYY-MM-DD` consolidation date). CELLAR stores the
|
|
27
|
-
* canonical OJ-manifestation literal (`…/{number}/oj`) rather than the bare
|
|
28
|
-
* work-level form, so these never match on exact lookup and must be normalized
|
|
29
|
-
* to their `/oj` form to resolve.
|
|
30
|
-
*/
|
|
31
|
-
function isBareWorkLevelEli(eli) {
|
|
32
|
-
if (!eli.startsWith(ELI_NAMESPACE))
|
|
33
|
-
return false;
|
|
34
|
-
const path = eli.slice(ELI_NAMESPACE.length).replace(/\/+$/, '');
|
|
35
|
-
return /^[^/]+\/\d{4}\/[^/]+$/.test(path);
|
|
36
|
-
}
|
|
37
|
-
/** Escape backslashes then double-quotes for safe interpolation into a SPARQL string literal. */
|
|
38
|
-
function escapeSparqlLiteral(value) {
|
|
39
|
-
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* ELI exact-match query: resolve the single work whose canonical ELI literal
|
|
43
|
-
* (`cdm:resource_legal_eli`, an `xsd:anyURI` literal) equals `safeEli`, reading
|
|
44
|
-
* its CELEX, type, and date. `safeEli` must be pre-escaped.
|
|
45
|
-
*/
|
|
46
|
-
function buildEliQuery(safeEli) {
|
|
47
|
-
return `
|
|
48
|
-
SELECT ?work ?celexNumber ?type ?date WHERE {
|
|
49
|
-
?work cdm:resource_legal_eli "${safeEli}"^^xsd:anyURI .
|
|
50
|
-
?work cdm:resource_legal_id_celex ?celexNumber .
|
|
51
|
-
OPTIONAL { ?work cdm:work_has_resource-type ?type . }
|
|
52
|
-
OPTIONAL { ?work cdm:work_date_document ?date . }
|
|
53
|
-
} LIMIT 5`;
|
|
54
|
-
}
|
|
55
20
|
export const eurlex_lookup_celex = tool('eurlex_lookup_celex', {
|
|
56
21
|
title: 'Resolve EU Legal Citation',
|
|
57
22
|
description: 'Resolve an EU legal citation — a CELEX number or an ELI URI — to the canonical CELLAR work. ' +
|
|
@@ -113,50 +78,41 @@ export const eurlex_lookup_celex = tool('eurlex_lookup_celex', {
|
|
|
113
78
|
else {
|
|
114
79
|
effectiveType = input.identifier_type;
|
|
115
80
|
}
|
|
116
|
-
|
|
81
|
+
// ELI resolution (exact-match on cdm:resource_legal_eli, with the bare
|
|
82
|
+
// work-level /oj retry) is shared with eurlex_get_document — see
|
|
83
|
+
// services/cellar-sparql/eli-resolution.ts. The CELEX branch stays here: a
|
|
84
|
+
// direct exact-string match on the CELEX literal.
|
|
85
|
+
let binding;
|
|
117
86
|
if (effectiveType === 'celex') {
|
|
118
|
-
|
|
87
|
+
const celexQuery = `
|
|
119
88
|
SELECT ?work ?celexNumber ?type ?date WHERE {
|
|
120
89
|
?work cdm:resource_legal_id_celex ?celexNumber .
|
|
121
90
|
OPTIONAL { ?work cdm:work_has_resource-type ?type . }
|
|
122
91
|
OPTIONAL { ?work cdm:work_date_document ?date . }
|
|
123
92
|
FILTER(STR(?celexNumber) = "${escapeSparqlLiteral(identifier)}")
|
|
124
93
|
} LIMIT 5`;
|
|
94
|
+
const bindings = await svc.query(celexQuery, ctx);
|
|
95
|
+
binding = bindings[0] ?? null;
|
|
125
96
|
}
|
|
126
97
|
else {
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
let bindings = await svc.query(sparql, ctx);
|
|
130
|
-
// CELLAR stores only the OJ-manifestation ELI literal (…/{number}/oj), so a
|
|
131
|
-
// bare work-level ELI (…/{type}/{year}/{number}) — the most common citation
|
|
132
|
-
// form — misses on exact match. Retry once with /oj appended: a deterministic,
|
|
133
|
-
// one-to-one normalization to the same act's canonical manifestation. Gated to
|
|
134
|
-
// bare work-level ELIs, so a manifestation-suffixed ELI (e.g. a /YYYY-MM-DD
|
|
135
|
-
// consolidated version) never silently falls back to the original act.
|
|
136
|
-
let bareEliRetry = false;
|
|
137
|
-
if (bindings.length === 0 && effectiveType === 'eli' && isBareWorkLevelEli(identifier)) {
|
|
138
|
-
const ojEli = `${identifier.replace(/\/+$/, '')}/oj`;
|
|
139
|
-
bindings = await svc.query(buildEliQuery(escapeSparqlLiteral(ojEli)), ctx);
|
|
140
|
-
bareEliRetry = true;
|
|
98
|
+
binding = await resolveEliToWork(svc, identifier, ctx);
|
|
141
99
|
}
|
|
142
100
|
ctx.log.info('Citation lookup', {
|
|
143
101
|
identifier,
|
|
144
102
|
type: effectiveType,
|
|
145
|
-
|
|
146
|
-
resultCount: bindings.length,
|
|
103
|
+
found: binding !== null,
|
|
147
104
|
});
|
|
148
|
-
if (
|
|
105
|
+
if (!binding) {
|
|
149
106
|
throw ctx.fail('not_found', `No CELLAR work found for identifier: ${identifier}`, {
|
|
150
107
|
...ctx.recoveryFor('not_found'),
|
|
151
108
|
});
|
|
152
109
|
}
|
|
153
|
-
const first = bindings[0];
|
|
154
110
|
return {
|
|
155
111
|
found: true,
|
|
156
|
-
work_uri: CellarSparqlService.bindingValue(
|
|
157
|
-
celex_number: CellarSparqlService.bindingValue(
|
|
158
|
-
resource_type: CellarSparqlService.bindingValue(
|
|
159
|
-
date: CellarSparqlService.bindingValue(
|
|
112
|
+
work_uri: CellarSparqlService.bindingValue(binding, 'work'),
|
|
113
|
+
celex_number: CellarSparqlService.bindingValue(binding, 'celexNumber'),
|
|
114
|
+
resource_type: CellarSparqlService.bindingValue(binding, 'type'),
|
|
115
|
+
date: CellarSparqlService.bindingValue(binding, 'date'),
|
|
160
116
|
};
|
|
161
117
|
},
|
|
162
118
|
format: (result) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eurlex-lookup-celex.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-lookup-celex.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,EACL,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mDAAmD,CAAC;
|
|
1
|
+
{"version":3,"file":"eurlex-lookup-celex.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurlex-lookup-celex.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -65,7 +65,7 @@ export declare const allToolDefinitions: (import("@cyanheads/mcp-ts-core").ToolD
|
|
|
65
65
|
readonly when: "Virtuoso returned HTTP 200 with an error body — query malformed or timed out.";
|
|
66
66
|
readonly recovery: "Simplify the query or reduce the date range and retry.";
|
|
67
67
|
}], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
|
|
68
|
-
celex_number: import("zod").ZodString
|
|
68
|
+
celex_number: import("zod").ZodOptional<import("zod").ZodString>;
|
|
69
69
|
eli_uri: import("zod").ZodOptional<import("zod").ZodString>;
|
|
70
70
|
language: import("zod").ZodDefault<import("zod").ZodString>;
|
|
71
71
|
format: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
@@ -88,10 +88,15 @@ export declare const allToolDefinitions: (import("@cyanheads/mcp-ts-core").ToolD
|
|
|
88
88
|
language_fallback: import("zod").ZodOptional<import("zod").ZodString>;
|
|
89
89
|
content_format: import("zod").ZodString;
|
|
90
90
|
}, import("zod/v4/core").$strip>, readonly [{
|
|
91
|
+
readonly reason: "invalid_identifier_args";
|
|
92
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
93
|
+
readonly when: "Neither celex_number nor eli_uri was provided, or both were.";
|
|
94
|
+
readonly recovery: "Provide exactly one of celex_number or eli_uri.";
|
|
95
|
+
}, {
|
|
91
96
|
readonly reason: "not_found";
|
|
92
97
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
|
|
93
|
-
readonly when: "CELEX number not found in CELLAR — the work does not exist in the corpus.";
|
|
94
|
-
readonly recovery: "Verify the
|
|
98
|
+
readonly when: "CELEX number or ELI URI not found in CELLAR — the work does not exist in the corpus.";
|
|
99
|
+
readonly recovery: "Verify the identifier or use eurlex_lookup_celex to confirm it exists.";
|
|
95
100
|
}, {
|
|
96
101
|
readonly reason: "language_unavailable";
|
|
97
102
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
|
|
@@ -103,7 +108,7 @@ export declare const allToolDefinitions: (import("@cyanheads/mcp-ts-core").ToolD
|
|
|
103
108
|
readonly when: "EUR-Lex content API returned non-200 after language fallback attempts.";
|
|
104
109
|
readonly recovery: "The EUR-Lex content API may be temporarily unavailable. Retry after a short delay.";
|
|
105
110
|
}], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
|
|
106
|
-
celex_number: import("zod").ZodString
|
|
111
|
+
celex_number: import("zod").ZodOptional<import("zod").ZodString>;
|
|
107
112
|
work_uri: import("zod").ZodOptional<import("zod").ZodString>;
|
|
108
113
|
relation_types: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodEnum<{
|
|
109
114
|
cites: "cites";
|
|
@@ -113,8 +118,8 @@ export declare const allToolDefinitions: (import("@cyanheads/mcp-ts-core").ToolD
|
|
|
113
118
|
consolidated_version: "consolidated_version";
|
|
114
119
|
}>>>;
|
|
115
120
|
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
116
|
-
celex_number: import("zod").ZodString
|
|
117
|
-
work_uri: import("zod").
|
|
121
|
+
celex_number: import("zod").ZodOptional<import("zod").ZodString>;
|
|
122
|
+
work_uri: import("zod").ZodString;
|
|
118
123
|
relations: import("zod").ZodArray<import("zod").ZodObject<{
|
|
119
124
|
relation_type: import("zod").ZodString;
|
|
120
125
|
direction: import("zod").ZodString;
|
|
@@ -123,9 +128,14 @@ export declare const allToolDefinitions: (import("@cyanheads/mcp-ts-core").ToolD
|
|
|
123
128
|
}, import("zod/v4/core").$strip>>;
|
|
124
129
|
total: import("zod").ZodNumber;
|
|
125
130
|
}, import("zod/v4/core").$strip>, readonly [{
|
|
131
|
+
readonly reason: "invalid_identifier_args";
|
|
132
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
133
|
+
readonly when: "Neither celex_number nor work_uri was provided, or both were.";
|
|
134
|
+
readonly recovery: "Provide exactly one of celex_number or work_uri.";
|
|
135
|
+
}, {
|
|
126
136
|
readonly reason: "not_found";
|
|
127
137
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
|
|
128
|
-
readonly when: "CELEX
|
|
138
|
+
readonly when: "CELEX number not found in CELLAR — resolve the identifier with eurlex_lookup_celex first.";
|
|
129
139
|
readonly recovery: "Use eurlex_lookup_celex to confirm the CELEX number exists, then retry.";
|
|
130
140
|
}, {
|
|
131
141
|
readonly reason: "no_relations";
|
|
@@ -136,8 +146,8 @@ export declare const allToolDefinitions: (import("@cyanheads/mcp-ts-core").ToolD
|
|
|
136
146
|
identifier: import("zod").ZodString;
|
|
137
147
|
identifier_type: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
138
148
|
auto: "auto";
|
|
139
|
-
celex: "celex";
|
|
140
149
|
eli: "eli";
|
|
150
|
+
celex: "celex";
|
|
141
151
|
}>>;
|
|
142
152
|
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
143
153
|
found: import("zod").ZodBoolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,eAAO,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAQ9B,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview ELI URI → CELLAR work resolution, shared between eurlex_lookup_celex
|
|
3
|
+
* and eurlex_get_document. CELLAR stores the canonical OJ-manifestation ELI literal
|
|
4
|
+
* (`cdm:resource_legal_eli`, an `xsd:anyURI` literal), so a bare work-level ELI is
|
|
5
|
+
* normalized to its `/oj` form on a miss. Extracted from eurlex_lookup_celex (#5) so
|
|
6
|
+
* both tools resolve ELIs identically rather than duplicating the mechanism.
|
|
7
|
+
* @module services/cellar-sparql/eli-resolution
|
|
8
|
+
*/
|
|
9
|
+
import type { Context } from '@cyanheads/mcp-ts-core';
|
|
10
|
+
import type { CellarSparqlService } from './cellar-sparql-service.js';
|
|
11
|
+
import type { SparqlBinding } from './types.js';
|
|
12
|
+
/** ELI namespace prefix — all European Legislation Identifiers share this root. */
|
|
13
|
+
export declare const ELI_NAMESPACE = "http://data.europa.eu/eli/";
|
|
14
|
+
/** Detect ELI URI format: starts with http://data.europa.eu/eli/ */
|
|
15
|
+
export declare function isEliUri(identifier: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* A bare work-level ELI — `…/eli/{type}/{year}/{number}` with no manifestation
|
|
18
|
+
* suffix (no `/oj`, no `/YYYY-MM-DD` consolidation date). CELLAR stores the
|
|
19
|
+
* canonical OJ-manifestation literal (`…/{number}/oj`) rather than the bare
|
|
20
|
+
* work-level form, so these never match on exact lookup and must be normalized
|
|
21
|
+
* to their `/oj` form to resolve.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isBareWorkLevelEli(eli: string): boolean;
|
|
24
|
+
/** Escape backslashes then double-quotes for safe interpolation into a SPARQL string literal. */
|
|
25
|
+
export declare function escapeSparqlLiteral(value: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* ELI exact-match query: resolve the single work whose canonical ELI literal
|
|
28
|
+
* (`cdm:resource_legal_eli`, an `xsd:anyURI` literal) equals `safeEli`, reading
|
|
29
|
+
* its CELEX, type, and date. `safeEli` must be pre-escaped.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildEliQuery(safeEli: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve an ELI URI to its canonical CELLAR work binding.
|
|
34
|
+
*
|
|
35
|
+
* Exact-matches the ELI literal; a bare work-level ELI that misses is retried
|
|
36
|
+
* once with `/oj` appended — a deterministic, one-to-one normalization to the
|
|
37
|
+
* same act's canonical OJ manifestation. The retry is gated to bare work-level
|
|
38
|
+
* ELIs, so a manifestation-suffixed ELI (e.g. a `/YYYY-MM-DD` consolidated
|
|
39
|
+
* version) never silently falls back to the original act.
|
|
40
|
+
*
|
|
41
|
+
* Returns the first matching binding (with `?work ?celexNumber ?type ?date`),
|
|
42
|
+
* or `null` when the ELI resolves to no work.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveEliToWork(svc: Pick<CellarSparqlService, 'query'>, eli: string, ctx: Context): Promise<SparqlBinding | null>;
|
|
45
|
+
//# sourceMappingURL=eli-resolution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eli-resolution.d.ts","sourceRoot":"","sources":["../../../src/services/cellar-sparql/eli-resolution.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,mFAAmF;AACnF,eAAO,MAAM,aAAa,+BAA+B,CAAC;AAE1D,oEAAoE;AACpE,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAIvD;AAED,iGAAiG;AACjG,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQrD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,EACvC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAc/B"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview ELI URI → CELLAR work resolution, shared between eurlex_lookup_celex
|
|
3
|
+
* and eurlex_get_document. CELLAR stores the canonical OJ-manifestation ELI literal
|
|
4
|
+
* (`cdm:resource_legal_eli`, an `xsd:anyURI` literal), so a bare work-level ELI is
|
|
5
|
+
* normalized to its `/oj` form on a miss. Extracted from eurlex_lookup_celex (#5) so
|
|
6
|
+
* both tools resolve ELIs identically rather than duplicating the mechanism.
|
|
7
|
+
* @module services/cellar-sparql/eli-resolution
|
|
8
|
+
*/
|
|
9
|
+
/** ELI namespace prefix — all European Legislation Identifiers share this root. */
|
|
10
|
+
export const ELI_NAMESPACE = 'http://data.europa.eu/eli/';
|
|
11
|
+
/** Detect ELI URI format: starts with http://data.europa.eu/eli/ */
|
|
12
|
+
export function isEliUri(identifier) {
|
|
13
|
+
return identifier.trim().startsWith(ELI_NAMESPACE);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A bare work-level ELI — `…/eli/{type}/{year}/{number}` with no manifestation
|
|
17
|
+
* suffix (no `/oj`, no `/YYYY-MM-DD` consolidation date). CELLAR stores the
|
|
18
|
+
* canonical OJ-manifestation literal (`…/{number}/oj`) rather than the bare
|
|
19
|
+
* work-level form, so these never match on exact lookup and must be normalized
|
|
20
|
+
* to their `/oj` form to resolve.
|
|
21
|
+
*/
|
|
22
|
+
export function isBareWorkLevelEli(eli) {
|
|
23
|
+
if (!eli.startsWith(ELI_NAMESPACE))
|
|
24
|
+
return false;
|
|
25
|
+
const path = eli.slice(ELI_NAMESPACE.length).replace(/\/+$/, '');
|
|
26
|
+
return /^[^/]+\/\d{4}\/[^/]+$/.test(path);
|
|
27
|
+
}
|
|
28
|
+
/** Escape backslashes then double-quotes for safe interpolation into a SPARQL string literal. */
|
|
29
|
+
export function escapeSparqlLiteral(value) {
|
|
30
|
+
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* ELI exact-match query: resolve the single work whose canonical ELI literal
|
|
34
|
+
* (`cdm:resource_legal_eli`, an `xsd:anyURI` literal) equals `safeEli`, reading
|
|
35
|
+
* its CELEX, type, and date. `safeEli` must be pre-escaped.
|
|
36
|
+
*/
|
|
37
|
+
export function buildEliQuery(safeEli) {
|
|
38
|
+
return `
|
|
39
|
+
SELECT ?work ?celexNumber ?type ?date WHERE {
|
|
40
|
+
?work cdm:resource_legal_eli "${safeEli}"^^xsd:anyURI .
|
|
41
|
+
?work cdm:resource_legal_id_celex ?celexNumber .
|
|
42
|
+
OPTIONAL { ?work cdm:work_has_resource-type ?type . }
|
|
43
|
+
OPTIONAL { ?work cdm:work_date_document ?date . }
|
|
44
|
+
} LIMIT 5`;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Resolve an ELI URI to its canonical CELLAR work binding.
|
|
48
|
+
*
|
|
49
|
+
* Exact-matches the ELI literal; a bare work-level ELI that misses is retried
|
|
50
|
+
* once with `/oj` appended — a deterministic, one-to-one normalization to the
|
|
51
|
+
* same act's canonical OJ manifestation. The retry is gated to bare work-level
|
|
52
|
+
* ELIs, so a manifestation-suffixed ELI (e.g. a `/YYYY-MM-DD` consolidated
|
|
53
|
+
* version) never silently falls back to the original act.
|
|
54
|
+
*
|
|
55
|
+
* Returns the first matching binding (with `?work ?celexNumber ?type ?date`),
|
|
56
|
+
* or `null` when the ELI resolves to no work.
|
|
57
|
+
*/
|
|
58
|
+
export async function resolveEliToWork(svc, eli, ctx) {
|
|
59
|
+
const trimmed = eli.trim();
|
|
60
|
+
let bindings = await svc.query(buildEliQuery(escapeSparqlLiteral(trimmed)), ctx);
|
|
61
|
+
if (bindings.length === 0 && isBareWorkLevelEli(trimmed)) {
|
|
62
|
+
const ojEli = `${trimmed.replace(/\/+$/, '')}/oj`;
|
|
63
|
+
ctx.log.debug('ELI exact-match missed; retrying with /oj manifestation', {
|
|
64
|
+
eli: trimmed,
|
|
65
|
+
ojEli,
|
|
66
|
+
});
|
|
67
|
+
bindings = await svc.query(buildEliQuery(escapeSparqlLiteral(ojEli)), ctx);
|
|
68
|
+
}
|
|
69
|
+
return bindings[0] ?? null;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=eli-resolution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eli-resolution.js","sourceRoot":"","sources":["../../../src/services/cellar-sparql/eli-resolution.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,mFAAmF;AACnF,MAAM,CAAC,MAAM,aAAa,GAAG,4BAA4B,CAAC;AAE1D,oEAAoE;AACpE,MAAM,UAAU,QAAQ,CAAC,UAAkB;IACzC,OAAO,UAAU,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,KAAK,CAAC;IACjD,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACjE,OAAO,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO;;kCAEyB,OAAO;;;;UAI/B,CAAC;AACX,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAuC,EACvC,GAAW,EACX,GAAY;IAEZ,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,QAAQ,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAEjF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC;QAClD,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,yDAAyD,EAAE;YACvE,GAAG,EAAE,OAAO;YACZ,KAAK;SACN,CAAC,CAAC;QACH,QAAQ,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC7B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/eur-lex-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"mcpName": "io.github.cyanheads/eur-lex-mcp-server",
|
|
5
5
|
"description": "Search EU legislation, CJEU case law, and treaties; traverse the CELLAR relationship graph; resolve EuroVoc concepts via MCP. STDIO or Streamable HTTP.",
|
|
6
6
|
"type": "module",
|
package/server.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "https://github.com/cyanheads/eur-lex-mcp-server",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.2.0",
|
|
10
10
|
"remotes": [
|
|
11
11
|
{
|
|
12
12
|
"type": "streamable-http",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
20
20
|
"identifier": "@cyanheads/eur-lex-mcp-server",
|
|
21
21
|
"runtimeHint": "bun",
|
|
22
|
-
"version": "0.
|
|
22
|
+
"version": "0.2.0",
|
|
23
23
|
"packageArguments": [
|
|
24
24
|
{
|
|
25
25
|
"type": "positional",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
77
77
|
"identifier": "@cyanheads/eur-lex-mcp-server",
|
|
78
78
|
"runtimeHint": "bun",
|
|
79
|
-
"version": "0.
|
|
79
|
+
"version": "0.2.0",
|
|
80
80
|
"packageArguments": [
|
|
81
81
|
{
|
|
82
82
|
"type": "positional",
|