@cyanheads/eur-lex-mcp-server 0.4.0 → 0.4.2
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.4.x/0.4.1.md +14 -0
- package/changelog/0.4.x/0.4.2.md +16 -0
- package/dist/mcp-server/resources/definitions/eurlex-document-relations.resource.d.ts.map +1 -1
- package/dist/mcp-server/resources/definitions/eurlex-document-relations.resource.js +17 -51
- package/dist/mcp-server/resources/definitions/eurlex-document-relations.resource.js.map +1 -1
- package/dist/mcp-server/resources/definitions/eurlex-document.resource.d.ts.map +1 -1
- package/dist/mcp-server/resources/definitions/eurlex-document.resource.js +3 -3
- package/dist/mcp-server/resources/definitions/eurlex-document.resource.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-get-cases.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-get-cases.tool.js +66 -19
- package/dist/mcp-server/tools/definitions/eurlex-get-cases.tool.js.map +1 -1
- 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 +1 -2
- 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.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-get-relations.tool.js +19 -76
- 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 +0 -5
- 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 +6 -10
- package/dist/mcp-server/tools/definitions/eurlex-lookup-celex.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-query-sparql.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-query-sparql.tool.js +5 -3
- package/dist/mcp-server/tools/definitions/eurlex-query-sparql.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-search-documents.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurlex-search-documents.tool.js +70 -22
- package/dist/mcp-server/tools/definitions/eurlex-search-documents.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/index.d.ts +0 -5
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
- package/dist/services/cellar-sparql/cellar-sparql-service.d.ts +25 -2
- package/dist/services/cellar-sparql/cellar-sparql-service.d.ts.map +1 -1
- package/dist/services/cellar-sparql/cellar-sparql-service.js +34 -5
- package/dist/services/cellar-sparql/cellar-sparql-service.js.map +1 -1
- package/dist/services/cellar-sparql/relation-traversal.d.ts +28 -0
- package/dist/services/cellar-sparql/relation-traversal.d.ts.map +1 -0
- package/dist/services/cellar-sparql/relation-traversal.js +103 -0
- package/dist/services/cellar-sparql/relation-traversal.js.map +1 -0
- package/package.json +1 -1
- package/server.json +3 -3
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared CELLAR CDM relation traversal, used by the
|
|
3
|
+
* eurlex_get_relations tool and the eurlex://document/{celex}/relations
|
|
4
|
+
* resource. Owns the relation-type → CDM predicate + direction model so both
|
|
5
|
+
* surfaces resolve relations identically.
|
|
6
|
+
* @module services/cellar-sparql/relation-traversal
|
|
7
|
+
*/
|
|
8
|
+
import { CellarSparqlService } from './cellar-sparql-service.js';
|
|
9
|
+
/** The relation types this server exposes over the CDM graph. */
|
|
10
|
+
export const RELATION_TYPES = [
|
|
11
|
+
'cites',
|
|
12
|
+
'amends',
|
|
13
|
+
'amended_by',
|
|
14
|
+
'legal_basis',
|
|
15
|
+
'consolidated_version',
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* Per-relation-type CDM traversal spec: the predicate to follow and the
|
|
19
|
+
* direction(s) relative to the source work.
|
|
20
|
+
*
|
|
21
|
+
* CELLAR models amendment and consolidation one-directionally, so two types are
|
|
22
|
+
* the INCOMING side of a predicate whose name reads the other way — the
|
|
23
|
+
* dedicated `…amended_by…` and `…has_consolidated_version…` predicates carry
|
|
24
|
+
* zero triples:
|
|
25
|
+
* - `amended_by` is the incoming side of `…amends…` (`?amender amends <work>`).
|
|
26
|
+
* - `consolidated_version` is the incoming side of
|
|
27
|
+
* `…act_consolidated_consolidates…` (the consolidated act points back to the
|
|
28
|
+
* base; there is no forward `…has_consolidated_version…` link).
|
|
29
|
+
*
|
|
30
|
+
* `amends` and `legal_basis` are outgoing-only — their incoming rows describe a
|
|
31
|
+
* different relation (what amends this / what is based on this) and belong under
|
|
32
|
+
* `amended_by` and another work's `legal_basis`, not here. `cites` is symmetric
|
|
33
|
+
* ("citation graph"), so both directions are surfaced and tagged via `?direction`.
|
|
34
|
+
*/
|
|
35
|
+
const RELATION_SPECS = {
|
|
36
|
+
cites: { predicate: 'cdm:work_cites_work', direction: 'both' },
|
|
37
|
+
amends: { predicate: 'cdm:resource_legal_amends_resource_legal', direction: 'outgoing' },
|
|
38
|
+
amended_by: { predicate: 'cdm:resource_legal_amends_resource_legal', direction: 'incoming' },
|
|
39
|
+
legal_basis: { predicate: 'cdm:resource_legal_based_on_resource_legal', direction: 'outgoing' },
|
|
40
|
+
consolidated_version: {
|
|
41
|
+
predicate: 'cdm:act_consolidated_consolidates_resource_legal',
|
|
42
|
+
direction: 'incoming',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Default per-type result cap. Each relation type is queried independently with
|
|
47
|
+
* its own LIMIT so a high-volume type (e.g. `cites`) can't starve rarer types
|
|
48
|
+
* under a single shared cap. The service caps further if MAX_SPARQL_RESULTS is
|
|
49
|
+
* lower than this.
|
|
50
|
+
*/
|
|
51
|
+
export const DEFAULT_PER_TYPE_LIMIT = 100;
|
|
52
|
+
/** Build a single-relation-type SPARQL query for the given predicate + direction. */
|
|
53
|
+
function buildRelationQuery(workUri, spec, limit) {
|
|
54
|
+
const outgoing = `{
|
|
55
|
+
<${workUri}> ${spec.predicate} ?relatedWork .
|
|
56
|
+
OPTIONAL { ?relatedWork cdm:resource_legal_id_celex ?relatedCelex . }
|
|
57
|
+
BIND("outgoing" AS ?direction)
|
|
58
|
+
}`;
|
|
59
|
+
const incoming = `{
|
|
60
|
+
?relatedWork ${spec.predicate} <${workUri}> .
|
|
61
|
+
OPTIONAL { ?relatedWork cdm:resource_legal_id_celex ?relatedCelex . }
|
|
62
|
+
BIND("incoming" AS ?direction)
|
|
63
|
+
}`;
|
|
64
|
+
const body = spec.direction === 'outgoing'
|
|
65
|
+
? outgoing
|
|
66
|
+
: spec.direction === 'incoming'
|
|
67
|
+
? incoming
|
|
68
|
+
: `${outgoing} UNION ${incoming}`;
|
|
69
|
+
return `SELECT ?relatedWork ?relatedCelex ?direction WHERE {
|
|
70
|
+
${body}
|
|
71
|
+
} LIMIT ${limit}`;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Traverse the requested CDM relation types for a work — one query per type, run
|
|
75
|
+
* concurrently — and return de-duplicated relations tagged with their type and
|
|
76
|
+
* direction. Each type is resolved through its own query (and its own LIMIT) so
|
|
77
|
+
* the per-type caps are independent.
|
|
78
|
+
*/
|
|
79
|
+
export async function traverseRelations(svc, workUri, types, ctx, perTypeLimit = DEFAULT_PER_TYPE_LIMIT) {
|
|
80
|
+
const perType = await Promise.all(types.map(async (type) => ({
|
|
81
|
+
type,
|
|
82
|
+
bindings: await svc.query(buildRelationQuery(workUri, RELATION_SPECS[type], perTypeLimit), ctx),
|
|
83
|
+
})));
|
|
84
|
+
const seen = new Set();
|
|
85
|
+
const relations = [];
|
|
86
|
+
for (const { type, bindings } of perType) {
|
|
87
|
+
for (const b of bindings) {
|
|
88
|
+
const relatedWorkUri = CellarSparqlService.bindingValue(b, 'relatedWork') ?? '';
|
|
89
|
+
const direction = CellarSparqlService.bindingValue(b, 'direction') === 'incoming' ? 'incoming' : 'outgoing';
|
|
90
|
+
const key = `${type}|${direction}|${relatedWorkUri}`;
|
|
91
|
+
if (seen.has(key))
|
|
92
|
+
continue;
|
|
93
|
+
seen.add(key);
|
|
94
|
+
const relation = { relationType: type, direction, relatedWorkUri };
|
|
95
|
+
const relatedCelex = CellarSparqlService.bindingValue(b, 'relatedCelex');
|
|
96
|
+
if (relatedCelex)
|
|
97
|
+
relation.relatedCelexNumber = relatedCelex;
|
|
98
|
+
relations.push(relation);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return relations;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=relation-traversal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relation-traversal.js","sourceRoot":"","sources":["../../../src/services/cellar-sparql/relation-traversal.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/eur-lex-mcp-server",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
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.4.
|
|
9
|
+
"version": "0.4.2",
|
|
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.4.
|
|
22
|
+
"version": "0.4.2",
|
|
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.4.
|
|
79
|
+
"version": "0.4.2",
|
|
80
80
|
"packageArguments": [
|
|
81
81
|
{
|
|
82
82
|
"type": "positional",
|