@aborruso/ckan-mcp-server 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/openspec/apply.md +23 -0
- package/.claude/commands/openspec/archive.md +27 -0
- package/.claude/commands/openspec/proposal.md +28 -0
- package/.claude/settings.local.json +31 -0
- package/.gemini/commands/openspec/apply.toml +21 -0
- package/.gemini/commands/openspec/archive.toml +25 -0
- package/.gemini/commands/openspec/proposal.toml +26 -0
- package/.mcp.json +12 -0
- package/.opencode/command/openspec-apply.md +24 -0
- package/.opencode/command/openspec-archive.md +27 -0
- package/.opencode/command/openspec-proposal.md +29 -0
- package/AGENTS.md +18 -0
- package/CLAUDE.md +320 -0
- package/EXAMPLES.md +707 -0
- package/LICENSE.txt +21 -0
- package/LOG.md +154 -0
- package/PRD.md +912 -0
- package/README.md +468 -0
- package/REFACTORING.md +237 -0
- package/dist/index.js +1277 -0
- package/openspec/AGENTS.md +456 -0
- package/openspec/changes/archive/2026-01-08-add-mcp-resources/design.md +115 -0
- package/openspec/changes/archive/2026-01-08-add-mcp-resources/proposal.md +52 -0
- package/openspec/changes/archive/2026-01-08-add-mcp-resources/specs/mcp-resources/spec.md +92 -0
- package/openspec/changes/archive/2026-01-08-add-mcp-resources/tasks.md +56 -0
- package/openspec/changes/archive/2026-01-08-expand-test-coverage-specs/design.md +355 -0
- package/openspec/changes/archive/2026-01-08-expand-test-coverage-specs/proposal.md +161 -0
- package/openspec/changes/archive/2026-01-08-expand-test-coverage-specs/tasks.md +162 -0
- package/openspec/changes/archive/2026-01-08-translate-project-to-english/proposal.md +115 -0
- package/openspec/changes/archive/2026-01-08-translate-project-to-english/specs/documentation-language/spec.md +32 -0
- package/openspec/changes/archive/2026-01-08-translate-project-to-english/tasks.md +115 -0
- package/openspec/changes/archive/add-automated-tests/design.md +324 -0
- package/openspec/changes/archive/add-automated-tests/proposal.md +167 -0
- package/openspec/changes/archive/add-automated-tests/specs/automated-testing/spec.md +143 -0
- package/openspec/changes/archive/add-automated-tests/tasks.md +132 -0
- package/openspec/project.md +113 -0
- package/openspec/specs/documentation-language/spec.md +32 -0
- package/openspec/specs/mcp-resources/spec.md +94 -0
- package/package.json +46 -0
- package/spunti.md +19 -0
- package/tasks/todo.md +124 -0
- package/test-urls.js +18 -0
- package/tmp/test-org-search.js +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
# CKAN MCP Server
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for interacting with CKAN-based open data portals.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ Support for any CKAN server (dati.gov.it, data.gov, demo.ckan.org, etc.)
|
|
8
|
+
- 🔍 Advanced search with Solr syntax
|
|
9
|
+
- 📊 DataStore queries for tabular data analysis
|
|
10
|
+
- 🏢 Organization and group exploration
|
|
11
|
+
- 📦 Complete dataset and resource metadata
|
|
12
|
+
- 🎨 Output in Markdown or JSON format
|
|
13
|
+
- ⚡ Pagination and faceting support
|
|
14
|
+
- 📄 MCP Resource Templates for direct data access
|
|
15
|
+
- 🧪 Comprehensive test suite (101 tests, 100% passing)
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
### From npm (recommended)
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install ckan-mcp-server
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### From source
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Clone or copy the project
|
|
29
|
+
cd ckan-mcp-server
|
|
30
|
+
|
|
31
|
+
# Install dependencies
|
|
32
|
+
npm install
|
|
33
|
+
|
|
34
|
+
# Build with esbuild (fast, ~4ms)
|
|
35
|
+
npm run build
|
|
36
|
+
|
|
37
|
+
# Run tests (101 tests)
|
|
38
|
+
npm test
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
### Start with stdio (for local integration)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm start
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Start with HTTP (for remote access)
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
TRANSPORT=http PORT=3000 npm start
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The server will be available at `http://localhost:3000/mcp`
|
|
56
|
+
|
|
57
|
+
## Claude Desktop Configuration
|
|
58
|
+
|
|
59
|
+
Add to Claude Desktop configuration file (`claude_desktop_config.json`):
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"ckan": {
|
|
65
|
+
"command": "node",
|
|
66
|
+
"args": ["/path/to/ckan-mcp-server/dist/index.js"]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Su macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
73
|
+
Su Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
74
|
+
Su Linux: `~/.config/Claude/claude_desktop_config.json`
|
|
75
|
+
|
|
76
|
+
## Available Tools
|
|
77
|
+
|
|
78
|
+
### Search and Discovery
|
|
79
|
+
|
|
80
|
+
- **ckan_package_search**: Search datasets with Solr queries
|
|
81
|
+
- **ckan_package_show**: Complete details of a dataset
|
|
82
|
+
- **ckan_package_list**: List all datasets
|
|
83
|
+
|
|
84
|
+
### Organizations
|
|
85
|
+
|
|
86
|
+
- **ckan_organization_list**: List all organizations
|
|
87
|
+
- **ckan_organization_show**: Details of an organization
|
|
88
|
+
|
|
89
|
+
### DataStore
|
|
90
|
+
|
|
91
|
+
- **ckan_datastore_search**: Query tabular data
|
|
92
|
+
- **ckan_datastore_search_sql**: SQL queries (in development)
|
|
93
|
+
|
|
94
|
+
### Utilities
|
|
95
|
+
|
|
96
|
+
- **ckan_status_show**: Verify server status
|
|
97
|
+
|
|
98
|
+
## MCP Resource Templates
|
|
99
|
+
|
|
100
|
+
Direct data access via `ckan://` URI scheme:
|
|
101
|
+
|
|
102
|
+
- `ckan://{server}/dataset/{id}` - Dataset metadata
|
|
103
|
+
- `ckan://{server}/resource/{id}` - Resource metadata and download URL
|
|
104
|
+
- `ckan://{server}/organization/{name}` - Organization details
|
|
105
|
+
|
|
106
|
+
Examples:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
ckan://dati.gov.it/dataset/vaccini-covid
|
|
110
|
+
ckan://demo.ckan.org/resource/abc-123
|
|
111
|
+
ckan://data.gov/organization/sample-org
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Usage Examples
|
|
115
|
+
|
|
116
|
+
### Search datasets on dati.gov.it
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
ckan_package_search({
|
|
120
|
+
server_url: "https://www.dati.gov.it/opendata",
|
|
121
|
+
q: "popolazione",
|
|
122
|
+
rows: 20
|
|
123
|
+
})
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Filter by organization
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
ckan_package_search({
|
|
130
|
+
server_url: "https://www.dati.gov.it/opendata",
|
|
131
|
+
fq: "organization:regione-siciliana",
|
|
132
|
+
sort: "metadata_modified desc"
|
|
133
|
+
})
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Search organizations with wildcard
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// Find all organizations containing "salute" in the name
|
|
140
|
+
ckan_package_search({
|
|
141
|
+
server_url: "https://www.dati.gov.it/opendata",
|
|
142
|
+
q: "organization:*salute*",
|
|
143
|
+
rows: 0,
|
|
144
|
+
facet_field: ["organization"],
|
|
145
|
+
facet_limit: 100
|
|
146
|
+
})
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Get statistics with faceting
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
ckan_package_search({
|
|
153
|
+
server_url: "https://www.dati.gov.it/opendata",
|
|
154
|
+
facet_field: ["organization", "tags", "res_format"],
|
|
155
|
+
rows: 0
|
|
156
|
+
})
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### DataStore Query
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
ckan_datastore_search({
|
|
163
|
+
server_url: "https://www.dati.gov.it/opendata",
|
|
164
|
+
resource_id: "abc-123-def",
|
|
165
|
+
filters: { "regione": "Sicilia", "anno": 2023 },
|
|
166
|
+
sort: "popolazione desc",
|
|
167
|
+
limit: 50
|
|
168
|
+
})
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Supported CKAN Portals
|
|
172
|
+
|
|
173
|
+
Some of the main compatible portals:
|
|
174
|
+
|
|
175
|
+
- 🇮🇹 **www.dati.gov.it/opendata** - Italy
|
|
176
|
+
- 🇺🇸 **data.gov** - United States
|
|
177
|
+
- 🇨🇦 **open.canada.ca/data** - Canada
|
|
178
|
+
- 🇬🇧 **data.gov.uk** - United Kingdom
|
|
179
|
+
- 🇪🇺 **data.europa.eu** - European Union
|
|
180
|
+
- 🌍 **demo.ckan.org** - CKAN Demo
|
|
181
|
+
- And 500+ more portals worldwide
|
|
182
|
+
|
|
183
|
+
### Portal View URL Templates
|
|
184
|
+
|
|
185
|
+
Some CKAN portals expose non-standard web URLs for viewing datasets or organizations. To support those cases, this project ships with `src/portals.json`, which maps known portal API URLs (and aliases) to custom view URL templates.
|
|
186
|
+
|
|
187
|
+
When generating a dataset or organization view link, the server:
|
|
188
|
+
- matches the `server_url` against `api_url` and `api_url_aliases` in `src/portals.json`
|
|
189
|
+
- uses the portal-specific `dataset_view_url` / `organization_view_url` template when available
|
|
190
|
+
- falls back to the generic defaults (`{server_url}/dataset/{name}` and `{server_url}/organization/{name}`)
|
|
191
|
+
|
|
192
|
+
You can extend `src/portals.json` by adding new entries under `portals` if a portal uses different web URL patterns.
|
|
193
|
+
|
|
194
|
+
## Advanced Solr Queries
|
|
195
|
+
|
|
196
|
+
CKAN uses Apache Solr for search. Examples:
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
# Basic search
|
|
200
|
+
q: "popolazione"
|
|
201
|
+
|
|
202
|
+
# Field search
|
|
203
|
+
q: "title:popolazione"
|
|
204
|
+
q: "notes:sanità"
|
|
205
|
+
|
|
206
|
+
# Boolean operators
|
|
207
|
+
q: "popolazione AND sicilia"
|
|
208
|
+
q: "popolazione OR abitanti"
|
|
209
|
+
q: "popolazione NOT censimento"
|
|
210
|
+
|
|
211
|
+
# Filters (fq)
|
|
212
|
+
fq: "organization:comune-palermo"
|
|
213
|
+
fq: "tags:sanità"
|
|
214
|
+
fq: "res_format:CSV"
|
|
215
|
+
|
|
216
|
+
# Wildcard
|
|
217
|
+
q: "popolaz*"
|
|
218
|
+
|
|
219
|
+
# Date range
|
|
220
|
+
fq: "metadata_modified:[2023-01-01T00:00:00Z TO *]"
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Advanced Query Examples
|
|
224
|
+
|
|
225
|
+
These real-world examples demonstrate powerful Solr query combinations tested on the Italian open data portal (dati.gov.it):
|
|
226
|
+
|
|
227
|
+
#### 1. Fuzzy Search + Date Math + Boosting
|
|
228
|
+
|
|
229
|
+
Find healthcare datasets (tolerating spelling errors) modified in the last 6 months, prioritizing title matches:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
ckan_package_search({
|
|
233
|
+
server_url: "https://www.dati.gov.it/opendata",
|
|
234
|
+
q: "(title:sanità~2^3 OR title:salute~2^3 OR notes:sanità~1) AND metadata_modified:[NOW-6MONTHS TO *]",
|
|
235
|
+
sort: "score desc, metadata_modified desc",
|
|
236
|
+
rows: 30
|
|
237
|
+
})
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Techniques used**:
|
|
241
|
+
- `sanità~2` - Fuzzy search with edit distance 2 (finds "sanita", "sanitá", minor typos)
|
|
242
|
+
- `^3` - Boosts title matches 3x higher in relevance scoring
|
|
243
|
+
- `NOW-6MONTHS` - Dynamic date math for rolling time windows
|
|
244
|
+
- Combined boolean logic with multiple field searches
|
|
245
|
+
|
|
246
|
+
**Results**: 871 datasets including hospital units, healthcare organizations, medical services
|
|
247
|
+
|
|
248
|
+
#### 2. Proximity Search + Complex Boolean
|
|
249
|
+
|
|
250
|
+
Environmental datasets where "inquinamento" and "aria" (air pollution) appear close together, excluding water-related datasets:
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
ckan_package_search({
|
|
254
|
+
server_url: "https://www.dati.gov.it/opendata",
|
|
255
|
+
q: "(notes:\"inquinamento aria\"~5 OR title:\"qualità aria\"~3) AND NOT (title:acqua OR title:mare)",
|
|
256
|
+
facet_field: ["organization", "res_format"],
|
|
257
|
+
rows: 25
|
|
258
|
+
})
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Techniques used**:
|
|
262
|
+
- `"inquinamento aria"~5` - Proximity search (words within 5 positions)
|
|
263
|
+
- `~3` - Tighter proximity for title matches
|
|
264
|
+
- `NOT (title:acqua OR title:mare)` - Exclude water/sea datasets
|
|
265
|
+
- Faceting for statistical breakdown
|
|
266
|
+
|
|
267
|
+
**Results**: 306 datasets, primarily air quality monitoring from Milan (44) and Palermo (161), formats: XML (150), CSV (124), JSON (76)
|
|
268
|
+
|
|
269
|
+
#### 3. Wildcard + Field Existence + Range Queries
|
|
270
|
+
|
|
271
|
+
Regional datasets with at least 5 resources, published in the last year:
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
ckan_package_search({
|
|
275
|
+
server_url: "https://www.dati.gov.it/opendata",
|
|
276
|
+
q: "organization:regione* AND num_resources:[5 TO *] AND metadata_created:[NOW-1YEAR TO *] AND res_format:*",
|
|
277
|
+
sort: "num_resources desc, metadata_modified desc",
|
|
278
|
+
facet_field: ["organization"],
|
|
279
|
+
rows: 40
|
|
280
|
+
})
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Techniques used**:
|
|
284
|
+
- `regione*` - Wildcard matches all regional organizations
|
|
285
|
+
- `[5 TO *]` - Inclusive range (5 or more resources)
|
|
286
|
+
- `res_format:*` - Field existence check (has at least one resource format)
|
|
287
|
+
- `NOW-1YEAR` - Rolling 12-month window
|
|
288
|
+
|
|
289
|
+
**Results**: 5,318 datasets, top contributors: Lombardy (3,012), Tuscany (1,151), Puglia (460)
|
|
290
|
+
|
|
291
|
+
#### 4. Date Ranges + Exclusive Bounds
|
|
292
|
+
|
|
293
|
+
ISTAT datasets with moderate resource count (10-50), modified in specific date range:
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
ckan_package_search({
|
|
297
|
+
server_url: "https://www.dati.gov.it/opendata",
|
|
298
|
+
q: "(title:istat OR organization:*istat*) AND num_resources:{9 TO 51} AND metadata_modified:[2025-07-01T00:00:00Z TO 2025-12-31T23:59:59Z]",
|
|
299
|
+
sort: "metadata_modified desc",
|
|
300
|
+
facet_field: ["res_format", "tags"],
|
|
301
|
+
rows: 30
|
|
302
|
+
})
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Techniques used**:
|
|
306
|
+
- `{9 TO 51}` - Exclusive bounds (10-50 resources, excluding 9 and 51)
|
|
307
|
+
- `[2025-07-01T00:00:00Z TO 2025-12-31T23:59:59Z]` - Explicit date range
|
|
308
|
+
- Combined organization wildcard with title search
|
|
309
|
+
- Multiple facets for content analysis
|
|
310
|
+
|
|
311
|
+
**Note**: This specific query returned 0 results due to the narrow time window, demonstrating how precise constraints work.
|
|
312
|
+
|
|
313
|
+
### Solr Query Syntax Reference
|
|
314
|
+
|
|
315
|
+
**Boolean Operators**: `AND`, `OR`, `NOT`, `+required`, `-excluded`
|
|
316
|
+
**Wildcards**: `*` (multiple chars), `?` (single char) - Note: left truncation not supported
|
|
317
|
+
**Fuzzy**: `~N` (edit distance), e.g., `health~2`
|
|
318
|
+
**Proximity**: `"phrase"~N` (words within N positions)
|
|
319
|
+
**Boosting**: `^N` (relevance multiplier), e.g., `title:water^2`
|
|
320
|
+
**Ranges**:
|
|
321
|
+
- Inclusive: `[a TO b]`, e.g., `num_resources:[5 TO 10]`
|
|
322
|
+
- Exclusive: `{a TO b}`, e.g., `num_resources:{0 TO 100}`
|
|
323
|
+
- Open-ended: `[2024-01-01T00:00:00Z TO *]`
|
|
324
|
+
**Date Math**: `NOW`, `NOW-1YEAR`, `NOW-6MONTHS`, `NOW-7DAYS`, `NOW/DAY`
|
|
325
|
+
**Field Existence**: `field:*` (field exists), `NOT field:*` (field missing)
|
|
326
|
+
|
|
327
|
+
## Project Structure
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
ckan-mcp-server/
|
|
331
|
+
├── src/
|
|
332
|
+
│ ├── index.ts # Entry point
|
|
333
|
+
│ ├── server.ts # MCP server setup
|
|
334
|
+
│ ├── types.ts # Types & schemas
|
|
335
|
+
│ ├── utils/
|
|
336
|
+
│ │ ├── http.ts # CKAN API client
|
|
337
|
+
│ │ └── formatting.ts # Output formatting
|
|
338
|
+
│ ├── tools/
|
|
339
|
+
│ │ ├── package.ts # Package search/show
|
|
340
|
+
│ │ ├── organization.ts # Organization tools
|
|
341
|
+
│ │ ├── datastore.ts # DataStore queries
|
|
342
|
+
│ │ └── status.ts # Server status
|
|
343
|
+
│ ├── resources/ # MCP Resource Templates
|
|
344
|
+
│ │ ├── index.ts
|
|
345
|
+
│ │ ├── uri.ts # URI parsing
|
|
346
|
+
│ │ ├── dataset.ts
|
|
347
|
+
│ │ ├── resource.ts
|
|
348
|
+
│ │ └── organization.ts
|
|
349
|
+
│ └── transport/
|
|
350
|
+
│ ├── stdio.ts # Stdio transport
|
|
351
|
+
│ └── http.ts # HTTP transport
|
|
352
|
+
├── tests/ # Test suite (101 tests)
|
|
353
|
+
├── dist/ # Compiled files (generated)
|
|
354
|
+
├── package.json
|
|
355
|
+
└── README.md
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Development
|
|
359
|
+
|
|
360
|
+
### Testing
|
|
361
|
+
|
|
362
|
+
The project uses **Vitest** for automated testing:
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
# Run all tests
|
|
366
|
+
npm test
|
|
367
|
+
|
|
368
|
+
# Run tests in watch mode
|
|
369
|
+
npm run test:watch
|
|
370
|
+
|
|
371
|
+
# Run tests with coverage report
|
|
372
|
+
npm run test:coverage
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
Test coverage target is 80%. Current test suite includes:
|
|
376
|
+
- Unit tests for utility functions (formatting, HTTP)
|
|
377
|
+
- Integration tests for MCP tools with mocked CKAN API responses
|
|
378
|
+
- Mock fixtures for CKAN API success and error scenarios
|
|
379
|
+
|
|
380
|
+
See `tests/README.md` for detailed testing guidelines.
|
|
381
|
+
|
|
382
|
+
### Build
|
|
383
|
+
|
|
384
|
+
The project uses **esbuild** for ultra-fast compilation (~4ms):
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
# Build with esbuild (default)
|
|
388
|
+
npm run build
|
|
389
|
+
|
|
390
|
+
# Watch mode for development
|
|
391
|
+
npm run watch
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Manual Testing
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
# Start server in HTTP mode
|
|
398
|
+
TRANSPORT=http PORT=3000 npm start
|
|
399
|
+
|
|
400
|
+
# In another terminal, test available tools
|
|
401
|
+
curl -X POST http://localhost:3000/mcp \
|
|
402
|
+
-H 'Content-Type: application/json' \
|
|
403
|
+
-H 'Accept: application/json, text/event-stream' \
|
|
404
|
+
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## Troubleshooting
|
|
408
|
+
|
|
409
|
+
### dati.gov.it URL
|
|
410
|
+
|
|
411
|
+
**Important**: The correct URL for the Italian portal is `https://www.dati.gov.it/opendata` (not `https://dati.gov.it`).
|
|
412
|
+
|
|
413
|
+
### Connection error
|
|
414
|
+
|
|
415
|
+
```
|
|
416
|
+
Error: Server not found: https://esempio.gov.it
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**Solution**: Verify the URL is correct and the server is online. Use `ckan_status_show` to verify.
|
|
420
|
+
|
|
421
|
+
### No results
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
// Use a more generic query
|
|
425
|
+
ckan_package_search({
|
|
426
|
+
server_url: "https://www.dati.gov.it/opendata",
|
|
427
|
+
q: "*:*"
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
// Check contents with faceting
|
|
431
|
+
ckan_package_search({
|
|
432
|
+
server_url: "https://www.dati.gov.it/opendata",
|
|
433
|
+
facet_field: ["tags", "organization"],
|
|
434
|
+
rows: 0
|
|
435
|
+
})
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
## Contributing
|
|
439
|
+
|
|
440
|
+
Contributions are welcome! Please:
|
|
441
|
+
|
|
442
|
+
1. Fork the project
|
|
443
|
+
2. Create a branch for the feature (`git checkout -b feature/AmazingFeature`)
|
|
444
|
+
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
|
|
445
|
+
4. Push to the branch (`git push origin feature/AmazingFeature`)
|
|
446
|
+
5. Open a Pull Request
|
|
447
|
+
|
|
448
|
+
## License
|
|
449
|
+
|
|
450
|
+
MIT License - See LICENSE.txt file for complete details.
|
|
451
|
+
|
|
452
|
+
## Useful Links
|
|
453
|
+
|
|
454
|
+
- **CKAN**: https://ckan.org/
|
|
455
|
+
- **CKAN API Documentation**: https://docs.ckan.org/en/latest/api/
|
|
456
|
+
- **MCP Protocol**: https://modelcontextprotocol.io/
|
|
457
|
+
- **onData**: https://www.ondata.it/
|
|
458
|
+
- **dati.gov.it**: https://www.dati.gov.it/opendata/
|
|
459
|
+
|
|
460
|
+
## Support
|
|
461
|
+
|
|
462
|
+
For issues or questions:
|
|
463
|
+
- Open an issue on GitHub
|
|
464
|
+
- Contact onData: https://www.ondata.it/
|
|
465
|
+
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
Created with ❤️ by onData for the open data community
|
package/REFACTORING.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Refactoring Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Il codebase è stato refactorizzato da un singolo file monolitico di 1021 righe a una struttura modulare di 11 file.
|
|
6
|
+
|
|
7
|
+
## Motivazione
|
|
8
|
+
|
|
9
|
+
**Problemi del file unico**:
|
|
10
|
+
- 1021 righe difficili da navigare
|
|
11
|
+
- Modifiche rischiose (alta probabilità di errori)
|
|
12
|
+
- Testing complesso
|
|
13
|
+
- Code review difficili
|
|
14
|
+
- Merge conflicts probabili in collaborazione
|
|
15
|
+
|
|
16
|
+
**Vantaggi della struttura modulare**:
|
|
17
|
+
- File più piccoli (max 350 righe)
|
|
18
|
+
- Modifiche localizzate e sicure
|
|
19
|
+
- Testing isolato per tool
|
|
20
|
+
- Manutenzione semplificata
|
|
21
|
+
- Collaborazione efficiente
|
|
22
|
+
|
|
23
|
+
## Nuova Struttura
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
src/
|
|
27
|
+
├── index.ts # Entry point (39 lines)
|
|
28
|
+
├── server.ts # MCP server setup (12 lines)
|
|
29
|
+
├── types.ts # Types & schemas (16 lines)
|
|
30
|
+
├── utils/
|
|
31
|
+
│ ├── http.ts # CKAN API client (51 lines)
|
|
32
|
+
│ └── formatting.ts # Output formatting (37 lines)
|
|
33
|
+
├── tools/
|
|
34
|
+
│ ├── package.ts # Package tools (350 lines)
|
|
35
|
+
│ ├── organization.ts # Organization tools (341 lines)
|
|
36
|
+
│ ├── datastore.ts # DataStore tools (146 lines)
|
|
37
|
+
│ └── status.ts # Status tools (66 lines)
|
|
38
|
+
└── transport/
|
|
39
|
+
├── stdio.ts # Stdio transport (12 lines)
|
|
40
|
+
└── http.ts # HTTP transport (27 lines)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Total**: 1097 lines (vs 1021 original, +76 lines for better organization)
|
|
44
|
+
|
|
45
|
+
## File Descriptions
|
|
46
|
+
|
|
47
|
+
### Core Files
|
|
48
|
+
|
|
49
|
+
**`index.ts`** (Entry Point)
|
|
50
|
+
- Importa e registra tutti i tool
|
|
51
|
+
- Sceglie transport (stdio/http)
|
|
52
|
+
- Gestisce startup e error handling
|
|
53
|
+
|
|
54
|
+
**`server.ts`** (Server Configuration)
|
|
55
|
+
- Crea istanza MCP server
|
|
56
|
+
- Configurazione base (name, version)
|
|
57
|
+
|
|
58
|
+
**`types.ts`** (Type Definitions)
|
|
59
|
+
- `ResponseFormat` enum
|
|
60
|
+
- `ResponseFormatSchema` Zod validator
|
|
61
|
+
- `CHARACTER_LIMIT` constant
|
|
62
|
+
|
|
63
|
+
### Utils
|
|
64
|
+
|
|
65
|
+
**`utils/http.ts`** (HTTP Client)
|
|
66
|
+
- `makeCkanRequest<T>()` - HTTP client per CKAN API
|
|
67
|
+
- Normalizzazione URL
|
|
68
|
+
- Gestione errori (timeout, 404, network)
|
|
69
|
+
- User-Agent header
|
|
70
|
+
|
|
71
|
+
**`utils/formatting.ts`** (Output Formatting)
|
|
72
|
+
- `truncateText()` - Limita output a CHARACTER_LIMIT
|
|
73
|
+
- `formatDate()` - Format date in Italian locale
|
|
74
|
+
- `formatBytes()` - Human-readable file sizes
|
|
75
|
+
|
|
76
|
+
### Tools
|
|
77
|
+
|
|
78
|
+
**`tools/package.ts`** (Package/Dataset Tools)
|
|
79
|
+
- `ckan_package_search` - Search datasets (182 lines handler)
|
|
80
|
+
- `ckan_package_show` - Dataset details (138 lines handler)
|
|
81
|
+
|
|
82
|
+
**`tools/organization.ts`** (Organization Tools)
|
|
83
|
+
- `ckan_organization_list` - List organizations (118 lines)
|
|
84
|
+
- `ckan_organization_show` - Org details (95 lines)
|
|
85
|
+
- `ckan_organization_search` - Search orgs (102 lines)
|
|
86
|
+
|
|
87
|
+
**`tools/datastore.ts`** (DataStore Tools)
|
|
88
|
+
- `ckan_datastore_search` - Query tabular data (130 lines)
|
|
89
|
+
|
|
90
|
+
**`tools/status.ts`** (Status Tools)
|
|
91
|
+
- `ckan_status_show` - Check server status (51 lines)
|
|
92
|
+
|
|
93
|
+
### Transport
|
|
94
|
+
|
|
95
|
+
**`transport/stdio.ts`** (Stdio Transport)
|
|
96
|
+
- `runStdio()` - Standard input/output transport
|
|
97
|
+
- For Claude Desktop and local MCP clients
|
|
98
|
+
|
|
99
|
+
**`transport/http.ts`** (HTTP Transport)
|
|
100
|
+
- `runHTTP()` - HTTP server on configurable port
|
|
101
|
+
- For remote access via HTTP POST
|
|
102
|
+
|
|
103
|
+
## Build Configuration
|
|
104
|
+
|
|
105
|
+
**No changes needed** - esbuild continua a funzionare:
|
|
106
|
+
```bash
|
|
107
|
+
npm run build # 15ms build time
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
esbuild automaticamente:
|
|
111
|
+
- Bundle tutti i moduli interni
|
|
112
|
+
- Tree-shake codice non usato
|
|
113
|
+
- Mantiene external dependencies separate
|
|
114
|
+
- Produce singolo file `dist/index.js`
|
|
115
|
+
|
|
116
|
+
## Testing Results
|
|
117
|
+
|
|
118
|
+
✅ **Build**: Successful (15ms)
|
|
119
|
+
✅ **Tool Registration**: All 7 tools listed
|
|
120
|
+
✅ **Tool Execution**: `ckan_status_show` tested successfully
|
|
121
|
+
✅ **Backward Compatibility**: 100% - stessa API MCP
|
|
122
|
+
|
|
123
|
+
## Benefits Achieved
|
|
124
|
+
|
|
125
|
+
### Maintainability
|
|
126
|
+
- Ogni file < 350 righe (easy to understand)
|
|
127
|
+
- Moduli isolati (modifiche localizzate)
|
|
128
|
+
- Clear separation of concerns
|
|
129
|
+
|
|
130
|
+
### Testing
|
|
131
|
+
- Tool handlers isolati e testabili
|
|
132
|
+
- Utilities testabili indipendentemente
|
|
133
|
+
- Mock più facili per unit tests
|
|
134
|
+
|
|
135
|
+
### Collaboration
|
|
136
|
+
- Merge conflicts ridotti
|
|
137
|
+
- Code review più veloci
|
|
138
|
+
- Feature development parallelo possibile
|
|
139
|
+
|
|
140
|
+
### Performance
|
|
141
|
+
- Build time invariato: ~15ms
|
|
142
|
+
- Bundle size invariato: ~30KB
|
|
143
|
+
- Runtime performance identico
|
|
144
|
+
- Tree-shaking preservato
|
|
145
|
+
|
|
146
|
+
## Migration Notes
|
|
147
|
+
|
|
148
|
+
### Old Structure
|
|
149
|
+
```typescript
|
|
150
|
+
// src/index.ts (1021 lines)
|
|
151
|
+
// Everything in one file
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### New Structure
|
|
155
|
+
```typescript
|
|
156
|
+
// src/index.ts (39 lines)
|
|
157
|
+
import { createServer } from "./server.js";
|
|
158
|
+
import { registerPackageTools } from "./tools/package.js";
|
|
159
|
+
// ...
|
|
160
|
+
|
|
161
|
+
const server = createServer();
|
|
162
|
+
registerPackageTools(server);
|
|
163
|
+
// ...
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Backward Compatibility
|
|
167
|
+
|
|
168
|
+
✅ **Zero breaking changes**:
|
|
169
|
+
- Stessi tool MCP esposti
|
|
170
|
+
- Stessi parametri input
|
|
171
|
+
- Stesso formato output
|
|
172
|
+
- Stesso comportamento
|
|
173
|
+
|
|
174
|
+
### Old File Preserved
|
|
175
|
+
|
|
176
|
+
`src/index-old.ts` - Backup del file originale (per riferimento)
|
|
177
|
+
|
|
178
|
+
## Future Enhancements Enabled
|
|
179
|
+
|
|
180
|
+
Con la nuova struttura diventa più facile:
|
|
181
|
+
|
|
182
|
+
1. **Unit Testing**: Test singoli tool in isolamento
|
|
183
|
+
2. **New Tools**: Aggiungere tool in file separati
|
|
184
|
+
3. **Shared Logic**: Utilities riutilizzabili
|
|
185
|
+
4. **Documentation**: JSDoc per ogni modulo
|
|
186
|
+
5. **Type Safety**: Types centralizzati
|
|
187
|
+
6. **Optimization**: Ottimizzare singoli moduli
|
|
188
|
+
|
|
189
|
+
## Maintenance Guide
|
|
190
|
+
|
|
191
|
+
### Adding a New Tool
|
|
192
|
+
|
|
193
|
+
1. Create `src/tools/newtool.ts`:
|
|
194
|
+
```typescript
|
|
195
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
196
|
+
|
|
197
|
+
export function registerNewTools(server: McpServer) {
|
|
198
|
+
server.registerTool("tool_name", { ... }, async (params) => { ... });
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
2. Import in `src/index.ts`:
|
|
203
|
+
```typescript
|
|
204
|
+
import { registerNewTools } from "./tools/newtool.js";
|
|
205
|
+
registerNewTools(server);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
3. Build and test:
|
|
209
|
+
```bash
|
|
210
|
+
npm run build
|
|
211
|
+
npm start
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Modifying a Tool
|
|
215
|
+
|
|
216
|
+
1. Edit relevant file in `src/tools/`
|
|
217
|
+
2. Changes are isolated
|
|
218
|
+
3. Build and test
|
|
219
|
+
4. No risk to other tools
|
|
220
|
+
|
|
221
|
+
### Adding Utilities
|
|
222
|
+
|
|
223
|
+
1. Create in `src/utils/`
|
|
224
|
+
2. Export function
|
|
225
|
+
3. Import where needed
|
|
226
|
+
4. Automatic tree-shaking if unused
|
|
227
|
+
|
|
228
|
+
## Conclusion
|
|
229
|
+
|
|
230
|
+
Il refactoring è stato completato con successo:
|
|
231
|
+
- ✅ Struttura modulare
|
|
232
|
+
- ✅ Build funzionante
|
|
233
|
+
- ✅ Backward compatible
|
|
234
|
+
- ✅ Testing verificato
|
|
235
|
+
- ✅ Performance preserved
|
|
236
|
+
|
|
237
|
+
Il codice è ora più manutenibile, testabile e scalabile, mantenendo tutta la funzionalità originale.
|