Skip to content

Commit 8e8f462

Browse files
committed
fix(skill): correct europa.eu SPARQL and CKAN API documentation
- CKAN endpoint exists at /api/hub/search/ckan/ (not /api/3/action/) - ckan_package_search MCP tool cannot use it (wrong path suffix) - fq=country:XX returns 0 on CKAN endpoint (country nested in org) - SPARQL country filter via skos:exactMatch does not work (blank nodes) - Replace broken SPARQL examples with tested ones (theme, file type) - REST API via Bash is the only reliable country-filtered method
1 parent 356678a commit 8e8f462

2 files changed

Lines changed: 57 additions & 37 deletions

File tree

skills/ckan-mcp/SKILL.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,15 @@ See [references/europa-api.md](references/europa-api.md) for full API patterns.
8989
- `country=XX` filter is not strict — results may include nearby countries (e.g. BE, CH when filtering FR)
9090
- Many datasets lack English titles → use `lang=XX` matching the target country
9191
- Filter results post-fetch by `country.id` to remove off-target countries
92-
- Prefer `sparql_query` when exact country filtering is required
9392

94-
**When to use REST vs SPARQL**:
95-
- REST (`Bash` + curl): fast broad discovery, when approximate results are acceptable
96-
- SPARQL (`sparql_query`): exact country filter, date ranges, thematic filtering
93+
**SPARQL limitations on data.europa.eu**:
94+
- The endpoint is reachable and returns results for generic queries
95+
- Country filtering via `dct:spatial` + `skos:exactMatch` does **NOT** work — spatial values are blank nodes, not URIs
96+
- Do not use `sparql_query` for country-filtered searches on this portal
97+
- `sparql_query` is only useful for schema exploration or generic graph queries
98+
99+
**Default tool: always REST API via Bash**:
100+
- REST is the only reliable method for country-filtered searches on data.europa.eu
97101

98102
```
99103
Example: "Trova dati ambientali per Italia e Spagna"
@@ -103,9 +107,6 @@ Example: "Dati aperti francesi sull'energia"
103107
-> NOTE: data.gouv.fr is NOT CKAN
104108
-> Bash: curl "https://data.europa.eu/api/hub/search/search?q=energie+energy&country=FR&lang=fr&limit=10"
105109
-> Filter post-fetch: keep only items where country.id == "fr"
106-
107-
Example: "Dataset recenti sull'ambiente dal portale europeo" (precise)
108-
-> sparql_query(query="...", endpoint="https://data.europa.eu/sparql")
109110
```
110111

111112
### Flow D — Dataset Detail + DataStore

skills/ckan-mcp/references/europa-api.md

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -84,35 +84,41 @@ curl "https://data.europa.eu/api/hub/search/search?q=*&facets=country&limit=0"
8484

8585
## CKAN-Compatible API
8686

87-
data.europa.eu also exposes a CKAN-compatible endpoint:
87+
A CKAN-compatible endpoint exists at:
8888

8989
```
90-
POST https://data.europa.eu/ckan/api/3/action/package_search
90+
GET https://data.europa.eu/api/hub/search/ckan/package_search
91+
GET https://data.europa.eu/api/hub/search/ckan/package_show?id=DATASET_ID
9192
```
9293

93-
Use via MCP tool:
94+
**Cannot be used via `ckan_package_search` MCP tool** — the tool appends `/api/3/action/package_search` which does not exist on this portal (returns 404).
9495

95-
```
96-
ckan_package_search(
97-
server_url="https://data.europa.eu/ckan",
98-
q="environment",
99-
fq="country:IT"
100-
)
96+
**Country filtering does not work**`fq=country:FR` returns 0 results. Country info is nested inside `organization.country` in the response, not a top-level filterable field.
97+
98+
To use this endpoint, call it directly via Bash:
99+
100+
```bash
101+
curl "https://data.europa.eu/api/hub/search/ckan/package_search?q=water+quality&rows=10"
101102
```
102103

104+
For country-filtered searches, use the REST API instead (see above).
105+
103106
## SPARQL Endpoint
104107

105108
For structured linked-data queries using RDF/DCAT vocabulary.
106109

107110
```
108111
Endpoint: https://data.europa.eu/sparql
109112
Method: POST
110-
Content-Type: application/x-www-form-urlencoded
111-
Body: query=SELECT...&format=application/sparql-results+json
112113
```
113114

114115
Use via MCP tool: `sparql_query(query="...", endpoint="https://data.europa.eu/sparql")`
115116

117+
**SPARQL limitations**:
118+
- Country filtering via `dct:spatial` + `skos:exactMatch` does **NOT** work — spatial values on datasets are blank nodes, not country URIs
119+
- For country-filtered searches, use the REST API via Bash (the only reliable method)
120+
- SPARQL is useful for: theme filtering, file type filtering, specific dataset/distribution lookup
121+
116122
### Common Prefixes
117123

118124
```sparql
@@ -124,35 +130,48 @@ PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
124130
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
125131
```
126132

127-
### Example Queries
133+
### Example Queries (tested and working)
128134

129135
```sparql
130-
-- Datasets about environment from Italy, English titles
131-
SELECT ?dataset ?title ?issued WHERE {
132-
?dataset a dcat:Dataset ;
133-
dct:title ?title ;
134-
dct:issued ?issued ;
135-
dct:spatial ?spatial .
136-
?spatial skos:exactMatch <http://publications.europa.eu/resource/authority/country/ITA> .
137-
FILTER(LANG(?title) = "en")
138-
FILTER(CONTAINS(LCASE(STR(?title)), "environment"))
136+
-- Datasets by EU theme (Environment), with publisher and keywords
137+
SELECT DISTINCT ?datasetURI ?datasetTitle ?publisher (GROUP_CONCAT(?keyword; SEPARATOR = " | ") AS ?keywords)
138+
WHERE {
139+
?datasetURI a dcat:Dataset;
140+
dct:publisher/rdfs:label|dct:publisher/skos:prefLabel ?publisher;
141+
dcat:theme <http://publications.europa.eu/resource/authority/data-theme/ENVI>;
142+
dcat:keyword ?keyword;
143+
dct:title ?datasetTitle.
144+
FILTER(LANG(?datasetTitle)= "" || LANG(?datasetTitle) = "en").
145+
FILTER (LANG(?publisher) = "" || LANG(?publisher) = "en").
146+
}
147+
ORDER BY ?datasetURI
148+
LIMIT 10
149+
```
150+
151+
```sparql
152+
-- Distributions of a specific file type (e.g. XML)
153+
SELECT DISTINCT ?datasetURI ?accessURL ?OPLabel
154+
WHERE {
155+
?datasetURI a dcat:Dataset;
156+
dcat:distribution ?distributionURI.
157+
?distributionURI dcat:accessURL ?accessURL;
158+
dct:format ?OPFileType. FILTER(?OPFileType=<http://publications.europa.eu/resource/authority/file-type/XML>)
159+
?OPFileType skos:prefLabel ?OPLabel. FILTER(LANGMATCHES(LANG(?OPLabel),"en"))
139160
}
140-
ORDER BY DESC(?issued)
161+
ORDER BY ?datasetURI
141162
LIMIT 10
142163
```
143164

165+
### What does NOT work in SPARQL
166+
144167
```sparql
145-
-- Count datasets per country for a topic
146-
SELECT ?country (COUNT(?dataset) AS ?count) WHERE {
168+
-- BROKEN: country filter via skos:exactMatch — returns 0 results
169+
-- dct:spatial on datasets uses blank nodes, not country URIs
170+
SELECT ?dataset ?title WHERE {
147171
?dataset a dcat:Dataset ;
148-
dct:title ?title ;
149172
dct:spatial ?spatial .
150-
?spatial skos:exactMatch ?country .
151-
FILTER(CONTAINS(LCASE(STR(?title)), "climate"))
173+
?spatial skos:exactMatch <http://publications.europa.eu/resource/authority/country/ITA> .
152174
}
153-
GROUP BY ?country
154-
ORDER BY DESC(?count)
155-
LIMIT 20
156175
```
157176

158177
## EU Data Themes

0 commit comments

Comments
 (0)