@aborruso/ckan-mcp-server 0.3.2 → 0.4.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/.claude/settings.local.json +2 -1
- package/CLAUDE.md +81 -24
- package/LOG.md +72 -10
- package/README.md +87 -8
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/coverage-final.json +7 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +146 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/dist/worker.js +387 -0
- package/openspec/changes/add-cloudflare-workers/design.md +734 -0
- package/openspec/changes/add-cloudflare-workers/proposal.md +183 -0
- package/openspec/changes/add-cloudflare-workers/specs/cloudflare-deployment/spec.md +389 -0
- package/openspec/changes/add-cloudflare-workers/tasks.md +519 -0
- package/package.json +6 -2
- package/wrangler.toml +6 -0
- package/test-urls.js +0 -18
package/CLAUDE.md
CHANGED
|
@@ -41,7 +41,7 @@ The server exposes MCP tools for:
|
|
|
41
41
|
# Build project (uses esbuild - fast and lightweight)
|
|
42
42
|
npm run build
|
|
43
43
|
|
|
44
|
-
# Run test suite (
|
|
44
|
+
# Run test suite (113 tests - unit + integration)
|
|
45
45
|
npm test
|
|
46
46
|
|
|
47
47
|
# Watch mode for tests during development
|
|
@@ -61,6 +61,11 @@ npm run watch
|
|
|
61
61
|
|
|
62
62
|
# Build + run
|
|
63
63
|
npm run dev
|
|
64
|
+
|
|
65
|
+
# Cloudflare Workers deployment (v0.4.0+)
|
|
66
|
+
npm run build:worker # Build for Workers
|
|
67
|
+
npm run dev:worker # Test locally with Wrangler
|
|
68
|
+
npm run deploy # Deploy to Cloudflare Workers
|
|
64
69
|
```
|
|
65
70
|
|
|
66
71
|
### Build System
|
|
@@ -112,7 +117,8 @@ The server is implemented with a modular structure to improve maintainability an
|
|
|
112
117
|
|
|
113
118
|
```
|
|
114
119
|
src/
|
|
115
|
-
├── index.ts # Entry point (42 lines)
|
|
120
|
+
├── index.ts # Entry point Node.js (42 lines)
|
|
121
|
+
├── worker.ts # Entry point Cloudflare Workers (95 lines) [v0.4.0+]
|
|
116
122
|
├── server.ts # MCP server setup (12 lines)
|
|
117
123
|
├── types.ts # Types & schemas (16 lines)
|
|
118
124
|
├── utils/
|
|
@@ -134,7 +140,9 @@ src/
|
|
|
134
140
|
└── http.ts # HTTP transport (27 lines)
|
|
135
141
|
```
|
|
136
142
|
|
|
137
|
-
**Total**: ~
|
|
143
|
+
**Total**: ~1445 lines (including Workers deployment)
|
|
144
|
+
|
|
145
|
+
**Note**: `worker.ts` (v0.4.0+) is an alternative entry point for Cloudflare Workers deployment. Tool handlers (`tools/*`) are shared between Node.js and Workers runtimes.
|
|
138
146
|
|
|
139
147
|
The server (`src/index.ts`):
|
|
140
148
|
|
|
@@ -178,10 +186,32 @@ The server (`src/index.ts`):
|
|
|
178
186
|
|
|
179
187
|
### Transport Modes
|
|
180
188
|
|
|
181
|
-
The server
|
|
189
|
+
The server supports three transport modes:
|
|
182
190
|
|
|
183
191
|
- **stdio** (default): for integration with Claude Desktop and other local MCP clients
|
|
184
192
|
- **http**: exposes POST `/mcp` endpoint on configurable port (default 3000)
|
|
193
|
+
- **Cloudflare Workers** (v0.4.0+): global edge deployment via `src/worker.ts`
|
|
194
|
+
|
|
195
|
+
### Cloudflare Workers Deployment
|
|
196
|
+
|
|
197
|
+
**Added in v0.4.0**. The server can be deployed to Cloudflare Workers for global HTTP access.
|
|
198
|
+
|
|
199
|
+
**Key files**:
|
|
200
|
+
- `src/worker.ts` - Workers entry point using Web Standards transport
|
|
201
|
+
- `wrangler.toml` - Cloudflare configuration
|
|
202
|
+
|
|
203
|
+
**Deployment workflow**:
|
|
204
|
+
1. `npm run dev:worker` - Test locally (http://localhost:8787)
|
|
205
|
+
2. `npm run deploy` - Deploy to Cloudflare
|
|
206
|
+
3. Access at: `https://ckan-mcp-server.<account>.workers.dev`
|
|
207
|
+
|
|
208
|
+
**Architecture**:
|
|
209
|
+
- Uses `WebStandardStreamableHTTPServerTransport` from MCP SDK
|
|
210
|
+
- Compatible with Workers runtime (no Node.js APIs)
|
|
211
|
+
- Stateless mode (no session management)
|
|
212
|
+
- All 7 tools and 3 resource templates work identically to Node.js version
|
|
213
|
+
|
|
214
|
+
See `docs/DEPLOYMENT.md` for complete deployment guide.
|
|
185
215
|
|
|
186
216
|
### CKAN API Integration
|
|
187
217
|
|
|
@@ -293,28 +323,55 @@ curl -X POST http://localhost:3000/mcp \
|
|
|
293
323
|
To test with Claude Desktop, add MCP configuration to config file.
|
|
294
324
|
To test with Claude Desktop, add the MCP configuration to the config file.
|
|
295
325
|
|
|
296
|
-
##
|
|
326
|
+
## Development Notes
|
|
327
|
+
|
|
328
|
+
### Version History
|
|
297
329
|
|
|
298
|
-
|
|
299
|
-
|
|
330
|
+
**v0.4.0 (2026-01-10)**: Cloudflare Workers deployment
|
|
331
|
+
- Added `src/worker.ts` for Workers runtime
|
|
332
|
+
- Global edge deployment support
|
|
333
|
+
- Web Standards transport integration
|
|
334
|
+
- See `docs/DEPLOYMENT.md` for deployment guide
|
|
300
335
|
|
|
301
|
-
**
|
|
302
|
-
-
|
|
303
|
-
-
|
|
304
|
-
- Testing isolato possibile
|
|
305
|
-
- Manutenzione semplificata
|
|
306
|
-
- Zero breaking changes
|
|
336
|
+
**v0.3.0 (2026-01-08)**: MCP Resource Templates
|
|
337
|
+
- Added `ckan://` URI scheme support
|
|
338
|
+
- Direct data access for datasets, resources, organizations
|
|
307
339
|
|
|
308
|
-
|
|
309
|
-
-
|
|
310
|
-
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
-
|
|
314
|
-
-
|
|
340
|
+
**v0.2.0 (2026-01-08)**: Comprehensive test suite
|
|
341
|
+
- 113 tests (unit + integration)
|
|
342
|
+
- 97%+ code coverage
|
|
343
|
+
|
|
344
|
+
**v0.1.0 (2026-01-08)**: Modular refactoring
|
|
345
|
+
- Restructured from monolithic file to 11 modules
|
|
346
|
+
- Improved maintainability and testability
|
|
347
|
+
|
|
348
|
+
### Known Limitations
|
|
349
|
+
|
|
350
|
+
- **Output limit**: 50,000 characters hardcoded in `types.ts` (could be configurable)
|
|
351
|
+
- **Date formatting**: Uses 'it-IT' locale in `utils/formatting.ts` (could be parameterized)
|
|
352
|
+
- **Read-only**: All tools are read-only (no data modification on CKAN)
|
|
353
|
+
- **No caching**: Every request makes fresh HTTP call to CKAN APIs
|
|
354
|
+
- **No authentication**: Uses only public CKAN endpoints
|
|
355
|
+
- **No WebSocket**: MCP over HTTP uses JSON responses (not SSE streaming in Workers)
|
|
315
356
|
|
|
316
357
|
### Adding New Tools
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
358
|
+
|
|
359
|
+
1. Create new file in `src/tools/`
|
|
360
|
+
2. Export `registerXxxTools(server: McpServer)` function
|
|
361
|
+
3. Import and call in both `src/index.ts` and `src/worker.ts`
|
|
362
|
+
4. Add tests in `tests/integration/`
|
|
363
|
+
5. Build and test: `npm run build && npm test`
|
|
364
|
+
|
|
365
|
+
### Release Workflow
|
|
366
|
+
|
|
367
|
+
When releasing a new version:
|
|
368
|
+
|
|
369
|
+
1. **Update version**: Edit `package.json` version field
|
|
370
|
+
2. **Update LOG.md**: Add entry with date and changes
|
|
371
|
+
3. **Commit changes**: `git add . && git commit -m "..."`
|
|
372
|
+
4. **Push to GitHub**: `git push origin main`
|
|
373
|
+
5. **Create tag**: `git tag -a v0.x.0 -m "..." && git push origin v0.x.0`
|
|
374
|
+
6. **Publish to npm** (optional): `npm publish`
|
|
375
|
+
7. **Deploy to Cloudflare** (if code changed): `npm run deploy`
|
|
376
|
+
|
|
377
|
+
See `docs/DEPLOYMENT.md` for detailed Cloudflare deployment instructions.
|
package/LOG.md
CHANGED
|
@@ -1,17 +1,79 @@
|
|
|
1
1
|
# LOG
|
|
2
2
|
|
|
3
|
+
## 2026-01-10
|
|
4
|
+
|
|
5
|
+
### Version 0.4.0 - Cloudflare Workers Deployment ⭐
|
|
6
|
+
|
|
7
|
+
- **Production deployment**: Server now live on Cloudflare Workers
|
|
8
|
+
- Public endpoint: `https://ckan-mcp-server.andy-pr.workers.dev`
|
|
9
|
+
- Global edge deployment (low latency worldwide)
|
|
10
|
+
- Free tier: 100,000 requests/day
|
|
11
|
+
- Bundle size: 398KB (minified: 130KB gzipped)
|
|
12
|
+
- Cold start time: 58ms
|
|
13
|
+
|
|
14
|
+
- **New files**:
|
|
15
|
+
- `src/worker.ts` (95 lines): Workers entry point using Web Standards transport
|
|
16
|
+
- `wrangler.toml` (5 lines): Cloudflare Workers configuration
|
|
17
|
+
|
|
18
|
+
- **New npm scripts**:
|
|
19
|
+
- `build:worker`: Compile for Workers (browser platform, ESM format)
|
|
20
|
+
- `dev:worker`: Local testing with wrangler dev
|
|
21
|
+
- `deploy`: Build and deploy to Cloudflare
|
|
22
|
+
|
|
23
|
+
- **Architecture**:
|
|
24
|
+
- Uses `WebStandardStreamableHTTPServerTransport` from MCP SDK
|
|
25
|
+
- Compatible with Workers runtime (no Node.js APIs)
|
|
26
|
+
- Stateless mode (no session management)
|
|
27
|
+
- JSON responses enabled for simplicity
|
|
28
|
+
- CORS enabled for browser access
|
|
29
|
+
|
|
30
|
+
- **Testing**: All 7 MCP tools verified in Workers environment
|
|
31
|
+
- Health check: ✅ Working
|
|
32
|
+
- tools/list: ✅ Returns all 7 tools
|
|
33
|
+
- ckan_status_show: ✅ External CKAN API calls working
|
|
34
|
+
- Response times: < 2s for typical queries
|
|
35
|
+
|
|
36
|
+
- **Documentation**:
|
|
37
|
+
- Updated README.md with "Deployment Options" section
|
|
38
|
+
- Added Option 4 to Claude Desktop config (Workers HTTP transport)
|
|
39
|
+
- Created OpenSpec proposal in `openspec/changes/add-cloudflare-workers/`
|
|
40
|
+
|
|
41
|
+
- **No breaking changes**: stdio and self-hosted HTTP modes still fully supported
|
|
42
|
+
- Dual build system: Node.js bundle unchanged
|
|
43
|
+
- Existing tests (113) all passing
|
|
44
|
+
- Version bumped to 0.4.0
|
|
45
|
+
|
|
3
46
|
## 2026-01-09
|
|
4
47
|
|
|
5
|
-
###
|
|
6
|
-
- **
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
- **
|
|
48
|
+
### Version 0.3.2 - npm Publication
|
|
49
|
+
- **npm Publication**: Published to npm registry as `@aborruso/ckan-mcp-server`
|
|
50
|
+
- Package size: 68.6 KB (236 KB unpacked)
|
|
51
|
+
- Public access configured
|
|
52
|
+
- Installation time: 5 min → 30 sec (90% faster)
|
|
53
|
+
- User actions: 6 steps → 2 steps (67% reduction)
|
|
54
|
+
- **Global Command Support**: Added `bin` field to package.json
|
|
55
|
+
- Direct command: `ckan-mcp-server` (no node path required)
|
|
56
|
+
- Works system-wide after global install
|
|
57
|
+
- **Documentation Enhancement**: Three installation options in README
|
|
58
|
+
- Option 1: Global installation (recommended)
|
|
59
|
+
- Option 2: Local project installation
|
|
60
|
+
- Option 3: From source (development)
|
|
61
|
+
- Platform-specific paths (macOS, Windows, Linux)
|
|
62
|
+
- **GitHub Release**: Tagged v0.3.2 with release notes
|
|
63
|
+
- **Impact**: Low barrier to entry, standard npm workflow, better discoverability
|
|
64
|
+
|
|
65
|
+
### Project Evaluation v0.3.2
|
|
66
|
+
- **Overall Rating**: 9.0/10 (local evidence; external distribution not verified)
|
|
67
|
+
- **Distribution readiness**: 9/10 (metadata and CLI entry point verified)
|
|
68
|
+
- **Testing**: 113 tests passing; coverage 97%+ (2026-01-09)
|
|
69
|
+
- **Status**: Packaging and docs production-ready; npm/GitHub release require external verification
|
|
70
|
+
- See `docs/evaluation-v0.3.2.md` for full assessment
|
|
71
|
+
|
|
72
|
+
### Tests & Coverage Update
|
|
73
|
+
- Added unit tests for HTTP error branches and URL generator org paths
|
|
74
|
+
- Tests: `tests/unit/http.test.ts`, `tests/unit/url-generator.test.ts`
|
|
75
|
+
- `npm test`: 113 tests passing
|
|
76
|
+
- `npm run test:coverage`: 97.01% statements, 89.36% branches, 100% functions, 96.87% lines
|
|
15
77
|
|
|
16
78
|
### README Enhancement - Real-World Advanced Examples
|
|
17
79
|
- **New Section**: "Advanced Query Examples" in README.md
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ MCP (Model Context Protocol) server for interacting with CKAN-based open data po
|
|
|
12
12
|
- 🎨 Output in Markdown or JSON format
|
|
13
13
|
- ⚡ Pagination and faceting support
|
|
14
14
|
- 📄 MCP Resource Templates for direct data access
|
|
15
|
-
- 🧪 Comprehensive test suite (
|
|
15
|
+
- 🧪 Comprehensive test suite (113 tests, 100% passing)
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
@@ -34,7 +34,7 @@ npm install
|
|
|
34
34
|
# Build with esbuild (fast, ~4ms)
|
|
35
35
|
npm run build
|
|
36
36
|
|
|
37
|
-
# Run tests (
|
|
37
|
+
# Run tests (113 tests)
|
|
38
38
|
npm test
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -54,9 +54,65 @@ TRANSPORT=http PORT=3000 npm start
|
|
|
54
54
|
|
|
55
55
|
The server will be available at `http://localhost:3000/mcp`
|
|
56
56
|
|
|
57
|
+
## Deployment Options
|
|
58
|
+
|
|
59
|
+
### Option 1: Local Installation (stdio mode)
|
|
60
|
+
|
|
61
|
+
**Best for**: Personal use with Claude Desktop
|
|
62
|
+
|
|
63
|
+
Install and run locally on your machine (see Installation section above).
|
|
64
|
+
|
|
65
|
+
### Option 2: Self-Hosted HTTP Server
|
|
66
|
+
|
|
67
|
+
**Best for**: Team use, custom infrastructure
|
|
68
|
+
|
|
69
|
+
Deploy on your own server using Node.js:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
TRANSPORT=http PORT=3000 npm start
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Option 3: Cloudflare Workers ⭐ NEW
|
|
76
|
+
|
|
77
|
+
**Best for**: Global access, zero infrastructure, free hosting
|
|
78
|
+
|
|
79
|
+
Deploy to Cloudflare's edge network for worldwide low-latency access.
|
|
80
|
+
|
|
81
|
+
**Prerequisites**:
|
|
82
|
+
- Cloudflare account (free): https://dash.cloudflare.com/sign-up
|
|
83
|
+
- Wrangler CLI: `npm install -g wrangler`
|
|
84
|
+
|
|
85
|
+
**Quick Deploy**:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Clone repository
|
|
89
|
+
git clone https://github.com/aborruso/ckan-mcp-server.git
|
|
90
|
+
cd ckan-mcp-server
|
|
91
|
+
|
|
92
|
+
# Install dependencies
|
|
93
|
+
npm install
|
|
94
|
+
|
|
95
|
+
# Authenticate with Cloudflare
|
|
96
|
+
wrangler login
|
|
97
|
+
|
|
98
|
+
# Deploy to Workers
|
|
99
|
+
npm run deploy
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Your server will be live at: `https://ckan-mcp-server.<your-account>.workers.dev`
|
|
103
|
+
|
|
104
|
+
**Free tier includes**:
|
|
105
|
+
- 100,000 requests/day
|
|
106
|
+
- Global edge deployment
|
|
107
|
+
- Automatic HTTPS
|
|
108
|
+
- No cold starts
|
|
109
|
+
|
|
110
|
+
For detailed deployment instructions, see [DEPLOYMENT.md](docs/DEPLOYMENT.md).
|
|
111
|
+
|
|
57
112
|
## Claude Desktop Configuration
|
|
58
113
|
|
|
59
114
|
Configuration file location:
|
|
115
|
+
|
|
60
116
|
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
61
117
|
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
62
118
|
- **Linux**: `~/.config/Claude/claude_desktop_config.json`
|
|
@@ -119,6 +175,22 @@ If you cloned the repository:
|
|
|
119
175
|
}
|
|
120
176
|
```
|
|
121
177
|
|
|
178
|
+
### Option 4: Cloudflare Workers (HTTP transport)
|
|
179
|
+
|
|
180
|
+
Use the public Cloudflare Workers deployment (no local installation required):
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"mcpServers": {
|
|
185
|
+
"ckan": {
|
|
186
|
+
"url": "https://ckan-mcp-server.andy-pr.workers.dev/mcp"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Note**: This uses the public endpoint. You can also deploy your own Workers instance and use that URL instead.
|
|
193
|
+
|
|
122
194
|
## Available Tools
|
|
123
195
|
|
|
124
196
|
### Search and Discovery
|
|
@@ -231,6 +303,7 @@ Some of the main compatible portals:
|
|
|
231
303
|
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.
|
|
232
304
|
|
|
233
305
|
When generating a dataset or organization view link, the server:
|
|
306
|
+
|
|
234
307
|
- matches the `server_url` against `api_url` and `api_url_aliases` in `src/portals.json`
|
|
235
308
|
- uses the portal-specific `dataset_view_url` / `organization_view_url` template when available
|
|
236
309
|
- falls back to the generic defaults (`{server_url}/dataset/{name}` and `{server_url}/organization/{name}`)
|
|
@@ -284,6 +357,7 @@ ckan_package_search({
|
|
|
284
357
|
```
|
|
285
358
|
|
|
286
359
|
**Techniques used**:
|
|
360
|
+
|
|
287
361
|
- `sanità~2` - Fuzzy search with edit distance 2 (finds "sanita", "sanitá", minor typos)
|
|
288
362
|
- `^3` - Boosts title matches 3x higher in relevance scoring
|
|
289
363
|
- `NOW-6MONTHS` - Dynamic date math for rolling time windows
|
|
@@ -305,6 +379,7 @@ ckan_package_search({
|
|
|
305
379
|
```
|
|
306
380
|
|
|
307
381
|
**Techniques used**:
|
|
382
|
+
|
|
308
383
|
- `"inquinamento aria"~5` - Proximity search (words within 5 positions)
|
|
309
384
|
- `~3` - Tighter proximity for title matches
|
|
310
385
|
- `NOT (title:acqua OR title:mare)` - Exclude water/sea datasets
|
|
@@ -327,6 +402,7 @@ ckan_package_search({
|
|
|
327
402
|
```
|
|
328
403
|
|
|
329
404
|
**Techniques used**:
|
|
405
|
+
|
|
330
406
|
- `regione*` - Wildcard matches all regional organizations
|
|
331
407
|
- `[5 TO *]` - Inclusive range (5 or more resources)
|
|
332
408
|
- `res_format:*` - Field existence check (has at least one resource format)
|
|
@@ -349,6 +425,7 @@ ckan_package_search({
|
|
|
349
425
|
```
|
|
350
426
|
|
|
351
427
|
**Techniques used**:
|
|
428
|
+
|
|
352
429
|
- `{9 TO 51}` - Exclusive bounds (10-50 resources, excluding 9 and 51)
|
|
353
430
|
- `[2025-07-01T00:00:00Z TO 2025-12-31T23:59:59Z]` - Explicit date range
|
|
354
431
|
- Combined organization wildcard with title search
|
|
@@ -364,9 +441,11 @@ ckan_package_search({
|
|
|
364
441
|
**Proximity**: `"phrase"~N` (words within N positions)
|
|
365
442
|
**Boosting**: `^N` (relevance multiplier), e.g., `title:water^2`
|
|
366
443
|
**Ranges**:
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
444
|
+
|
|
445
|
+
- Inclusive: `[a TO b]`, e.g., `num_resources:[5 TO 10]`
|
|
446
|
+
- Exclusive: `{a TO b}`, e.g., `num_resources:{0 TO 100}`
|
|
447
|
+
- Open-ended: `[2024-01-01T00:00:00Z TO *]`
|
|
448
|
+
|
|
370
449
|
**Date Math**: `NOW`, `NOW-1YEAR`, `NOW-6MONTHS`, `NOW-7DAYS`, `NOW/DAY`
|
|
371
450
|
**Field Existence**: `field:*` (field exists), `NOT field:*` (field missing)
|
|
372
451
|
|
|
@@ -395,7 +474,7 @@ ckan-mcp-server/
|
|
|
395
474
|
│ └── transport/
|
|
396
475
|
│ ├── stdio.ts # Stdio transport
|
|
397
476
|
│ └── http.ts # HTTP transport
|
|
398
|
-
├── tests/ # Test suite (
|
|
477
|
+
├── tests/ # Test suite (113 tests)
|
|
399
478
|
├── dist/ # Compiled files (generated)
|
|
400
479
|
├── package.json
|
|
401
480
|
└── README.md
|
|
@@ -419,6 +498,7 @@ npm run test:coverage
|
|
|
419
498
|
```
|
|
420
499
|
|
|
421
500
|
Test coverage target is 80%. Current test suite includes:
|
|
501
|
+
|
|
422
502
|
- Unit tests for utility functions (formatting, HTTP)
|
|
423
503
|
- Integration tests for MCP tools with mocked CKAN API responses
|
|
424
504
|
- Mock fixtures for CKAN API success and error scenarios
|
|
@@ -500,12 +580,11 @@ MIT License - See LICENSE.txt file for complete details.
|
|
|
500
580
|
- **CKAN**: https://ckan.org/
|
|
501
581
|
- **CKAN API Documentation**: https://docs.ckan.org/en/latest/api/
|
|
502
582
|
- **MCP Protocol**: https://modelcontextprotocol.io/
|
|
503
|
-
- **onData**: https://www.ondata.it/
|
|
504
|
-
- **dati.gov.it**: https://www.dati.gov.it/opendata/
|
|
505
583
|
|
|
506
584
|
## Support
|
|
507
585
|
|
|
508
586
|
For issues or questions:
|
|
587
|
+
|
|
509
588
|
- Open an issue on GitHub
|
|
510
589
|
- Contact onData: https://www.ondata.it/
|
|
511
590
|
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
body, html {
|
|
2
|
+
margin:0; padding: 0;
|
|
3
|
+
height: 100%;
|
|
4
|
+
}
|
|
5
|
+
body {
|
|
6
|
+
font-family: Helvetica Neue, Helvetica, Arial;
|
|
7
|
+
font-size: 14px;
|
|
8
|
+
color:#333;
|
|
9
|
+
}
|
|
10
|
+
.small { font-size: 12px; }
|
|
11
|
+
*, *:after, *:before {
|
|
12
|
+
-webkit-box-sizing:border-box;
|
|
13
|
+
-moz-box-sizing:border-box;
|
|
14
|
+
box-sizing:border-box;
|
|
15
|
+
}
|
|
16
|
+
h1 { font-size: 20px; margin: 0;}
|
|
17
|
+
h2 { font-size: 14px; }
|
|
18
|
+
pre {
|
|
19
|
+
font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
|
20
|
+
margin: 0;
|
|
21
|
+
padding: 0;
|
|
22
|
+
-moz-tab-size: 2;
|
|
23
|
+
-o-tab-size: 2;
|
|
24
|
+
tab-size: 2;
|
|
25
|
+
}
|
|
26
|
+
a { color:#0074D9; text-decoration:none; }
|
|
27
|
+
a:hover { text-decoration:underline; }
|
|
28
|
+
.strong { font-weight: bold; }
|
|
29
|
+
.space-top1 { padding: 10px 0 0 0; }
|
|
30
|
+
.pad2y { padding: 20px 0; }
|
|
31
|
+
.pad1y { padding: 10px 0; }
|
|
32
|
+
.pad2x { padding: 0 20px; }
|
|
33
|
+
.pad2 { padding: 20px; }
|
|
34
|
+
.pad1 { padding: 10px; }
|
|
35
|
+
.space-left2 { padding-left:55px; }
|
|
36
|
+
.space-right2 { padding-right:20px; }
|
|
37
|
+
.center { text-align:center; }
|
|
38
|
+
.clearfix { display:block; }
|
|
39
|
+
.clearfix:after {
|
|
40
|
+
content:'';
|
|
41
|
+
display:block;
|
|
42
|
+
height:0;
|
|
43
|
+
clear:both;
|
|
44
|
+
visibility:hidden;
|
|
45
|
+
}
|
|
46
|
+
.fl { float: left; }
|
|
47
|
+
@media only screen and (max-width:640px) {
|
|
48
|
+
.col3 { width:100%; max-width:100%; }
|
|
49
|
+
.hide-mobile { display:none!important; }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.quiet {
|
|
53
|
+
color: #7f7f7f;
|
|
54
|
+
color: rgba(0,0,0,0.5);
|
|
55
|
+
}
|
|
56
|
+
.quiet a { opacity: 0.7; }
|
|
57
|
+
|
|
58
|
+
.fraction {
|
|
59
|
+
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
|
60
|
+
font-size: 10px;
|
|
61
|
+
color: #555;
|
|
62
|
+
background: #E8E8E8;
|
|
63
|
+
padding: 4px 5px;
|
|
64
|
+
border-radius: 3px;
|
|
65
|
+
vertical-align: middle;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
div.path a:link, div.path a:visited { color: #333; }
|
|
69
|
+
table.coverage {
|
|
70
|
+
border-collapse: collapse;
|
|
71
|
+
margin: 10px 0 0 0;
|
|
72
|
+
padding: 0;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
table.coverage td {
|
|
76
|
+
margin: 0;
|
|
77
|
+
padding: 0;
|
|
78
|
+
vertical-align: top;
|
|
79
|
+
}
|
|
80
|
+
table.coverage td.line-count {
|
|
81
|
+
text-align: right;
|
|
82
|
+
padding: 0 5px 0 20px;
|
|
83
|
+
}
|
|
84
|
+
table.coverage td.line-coverage {
|
|
85
|
+
text-align: right;
|
|
86
|
+
padding-right: 10px;
|
|
87
|
+
min-width:20px;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
table.coverage td span.cline-any {
|
|
91
|
+
display: inline-block;
|
|
92
|
+
padding: 0 5px;
|
|
93
|
+
width: 100%;
|
|
94
|
+
}
|
|
95
|
+
.missing-if-branch {
|
|
96
|
+
display: inline-block;
|
|
97
|
+
margin-right: 5px;
|
|
98
|
+
border-radius: 3px;
|
|
99
|
+
position: relative;
|
|
100
|
+
padding: 0 4px;
|
|
101
|
+
background: #333;
|
|
102
|
+
color: yellow;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.skip-if-branch {
|
|
106
|
+
display: none;
|
|
107
|
+
margin-right: 10px;
|
|
108
|
+
position: relative;
|
|
109
|
+
padding: 0 4px;
|
|
110
|
+
background: #ccc;
|
|
111
|
+
color: white;
|
|
112
|
+
}
|
|
113
|
+
.missing-if-branch .typ, .skip-if-branch .typ {
|
|
114
|
+
color: inherit !important;
|
|
115
|
+
}
|
|
116
|
+
.coverage-summary {
|
|
117
|
+
border-collapse: collapse;
|
|
118
|
+
width: 100%;
|
|
119
|
+
}
|
|
120
|
+
.coverage-summary tr { border-bottom: 1px solid #bbb; }
|
|
121
|
+
.keyline-all { border: 1px solid #ddd; }
|
|
122
|
+
.coverage-summary td, .coverage-summary th { padding: 10px; }
|
|
123
|
+
.coverage-summary tbody { border: 1px solid #bbb; }
|
|
124
|
+
.coverage-summary td { border-right: 1px solid #bbb; }
|
|
125
|
+
.coverage-summary td:last-child { border-right: none; }
|
|
126
|
+
.coverage-summary th {
|
|
127
|
+
text-align: left;
|
|
128
|
+
font-weight: normal;
|
|
129
|
+
white-space: nowrap;
|
|
130
|
+
}
|
|
131
|
+
.coverage-summary th.file { border-right: none !important; }
|
|
132
|
+
.coverage-summary th.pct { }
|
|
133
|
+
.coverage-summary th.pic,
|
|
134
|
+
.coverage-summary th.abs,
|
|
135
|
+
.coverage-summary td.pct,
|
|
136
|
+
.coverage-summary td.abs { text-align: right; }
|
|
137
|
+
.coverage-summary td.file { white-space: nowrap; }
|
|
138
|
+
.coverage-summary td.pic { min-width: 120px !important; }
|
|
139
|
+
.coverage-summary tfoot td { }
|
|
140
|
+
|
|
141
|
+
.coverage-summary .sorter {
|
|
142
|
+
height: 10px;
|
|
143
|
+
width: 7px;
|
|
144
|
+
display: inline-block;
|
|
145
|
+
margin-left: 0.5em;
|
|
146
|
+
background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
|
|
147
|
+
}
|
|
148
|
+
.coverage-summary .sorted .sorter {
|
|
149
|
+
background-position: 0 -20px;
|
|
150
|
+
}
|
|
151
|
+
.coverage-summary .sorted-desc .sorter {
|
|
152
|
+
background-position: 0 -10px;
|
|
153
|
+
}
|
|
154
|
+
.status-line { height: 10px; }
|
|
155
|
+
/* yellow */
|
|
156
|
+
.cbranch-no { background: yellow !important; color: #111; }
|
|
157
|
+
/* dark red */
|
|
158
|
+
.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
|
|
159
|
+
.low .chart { border:1px solid #C21F39 }
|
|
160
|
+
.highlighted,
|
|
161
|
+
.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
|
|
162
|
+
background: #C21F39 !important;
|
|
163
|
+
}
|
|
164
|
+
/* medium red */
|
|
165
|
+
.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
|
|
166
|
+
/* light red */
|
|
167
|
+
.low, .cline-no { background:#FCE1E5 }
|
|
168
|
+
/* light green */
|
|
169
|
+
.high, .cline-yes { background:rgb(230,245,208) }
|
|
170
|
+
/* medium green */
|
|
171
|
+
.cstat-yes { background:rgb(161,215,106) }
|
|
172
|
+
/* dark green */
|
|
173
|
+
.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
|
|
174
|
+
.high .chart { border:1px solid rgb(77,146,33) }
|
|
175
|
+
/* dark yellow (gold) */
|
|
176
|
+
.status-line.medium, .medium .cover-fill { background: #f9cd0b; }
|
|
177
|
+
.medium .chart { border:1px solid #f9cd0b; }
|
|
178
|
+
/* light yellow */
|
|
179
|
+
.medium { background: #fff4c2; }
|
|
180
|
+
|
|
181
|
+
.cstat-skip { background: #ddd; color: #111; }
|
|
182
|
+
.fstat-skip { background: #ddd; color: #111 !important; }
|
|
183
|
+
.cbranch-skip { background: #ddd !important; color: #111; }
|
|
184
|
+
|
|
185
|
+
span.cline-neutral { background: #eaeaea; }
|
|
186
|
+
|
|
187
|
+
.coverage-summary td.empty {
|
|
188
|
+
opacity: .5;
|
|
189
|
+
padding-top: 4px;
|
|
190
|
+
padding-bottom: 4px;
|
|
191
|
+
line-height: 1;
|
|
192
|
+
color: #888;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.cover-fill, .cover-empty {
|
|
196
|
+
display:inline-block;
|
|
197
|
+
height: 12px;
|
|
198
|
+
}
|
|
199
|
+
.chart {
|
|
200
|
+
line-height: 0;
|
|
201
|
+
}
|
|
202
|
+
.cover-empty {
|
|
203
|
+
background: white;
|
|
204
|
+
}
|
|
205
|
+
.cover-full {
|
|
206
|
+
border-right: none !important;
|
|
207
|
+
}
|
|
208
|
+
pre.prettyprint {
|
|
209
|
+
border: none !important;
|
|
210
|
+
padding: 0 !important;
|
|
211
|
+
margin: 0 !important;
|
|
212
|
+
}
|
|
213
|
+
.com { color: #999 !important; }
|
|
214
|
+
.ignore-none { color: #999; font-weight: normal; }
|
|
215
|
+
|
|
216
|
+
.wrapper {
|
|
217
|
+
min-height: 100%;
|
|
218
|
+
height: auto !important;
|
|
219
|
+
height: 100%;
|
|
220
|
+
margin: 0 auto -48px;
|
|
221
|
+
}
|
|
222
|
+
.footer, .push {
|
|
223
|
+
height: 48px;
|
|
224
|
+
}
|