@aborruso/ckan-mcp-server 0.4.8 โ 0.4.9
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 +188 -1
- package/CLAUDE.md +11 -8
- package/LOG.md +48 -0
- package/README.md +19 -17
- package/dist/worker.js +66 -49
- package/package.json +2 -2
- package/testo.md +12 -0
package/AGENTS.md
CHANGED
|
@@ -4,15 +4,202 @@
|
|
|
4
4
|
These instructions are for AI assistants working in this project.
|
|
5
5
|
|
|
6
6
|
Always open `@/openspec/AGENTS.md` when the request:
|
|
7
|
+
|
|
7
8
|
- Mentions planning or proposals (words like proposal, spec, change, plan)
|
|
8
9
|
- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
|
|
9
10
|
- Sounds ambiguous and you need the authoritative spec before coding
|
|
10
11
|
|
|
11
12
|
Use `@/openspec/AGENTS.md` to learn:
|
|
13
|
+
|
|
12
14
|
- How to create and apply change proposals
|
|
13
15
|
- Spec format and conventions
|
|
14
16
|
- Project structure and guidelines
|
|
15
17
|
|
|
16
18
|
Keep this managed block so 'openspec update' can refresh the instructions.
|
|
17
19
|
|
|
18
|
-
<!-- OPENSPEC:END -->
|
|
20
|
+
<!-- OPENSPEC:END -->
|
|
21
|
+
|
|
22
|
+
# Agent Guide
|
|
23
|
+
|
|
24
|
+
## Scope
|
|
25
|
+
|
|
26
|
+
- Repo: `ckan-mcp-server`
|
|
27
|
+
- Stack: Node.js + TypeScript (ESM)
|
|
28
|
+
- Tests: Vitest
|
|
29
|
+
- Build: esbuild
|
|
30
|
+
- Cloudflare Workers: `wrangler`
|
|
31
|
+
|
|
32
|
+
## Cursor and Copilot Rules
|
|
33
|
+
|
|
34
|
+
- No `.cursor/rules`, `.cursorrules`, or `.github/copilot-instructions.md` found
|
|
35
|
+
|
|
36
|
+
## Core Commands
|
|
37
|
+
|
|
38
|
+
Install deps:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Build (node bundle):
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm run build
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Build (worker bundle):
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm run build:worker
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
TypeScript build (tsc):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm run build:tsc
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Start server (stdio or HTTP via env):
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm start
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Dev build + run:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npm run dev
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Watch build:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm run watch
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Cloudflare dev:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm run dev:worker
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Deploy worker:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm run deploy
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Tests
|
|
93
|
+
|
|
94
|
+
Run all tests:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npm test
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Watch tests:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npm run test:watch
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Coverage:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npm run test:coverage
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Run a single file:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npm test -- tests/unit/http.test.ts
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Run a single test name:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
npm test -- -t "makeCkanRequest"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Run single file with Vitest directly:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npx vitest tests/unit/http.test.ts
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Lint and Format
|
|
131
|
+
|
|
132
|
+
- No ESLint or Prettier config detected
|
|
133
|
+
- Do not add new formatters unless requested
|
|
134
|
+
- Keep formatting consistent with existing files
|
|
135
|
+
|
|
136
|
+
## Project Layout
|
|
137
|
+
|
|
138
|
+
- `src/index.ts` entry point
|
|
139
|
+
- `src/server.ts` server wiring
|
|
140
|
+
- `src/tools/` MCP tool handlers
|
|
141
|
+
- `src/utils/` helpers (http, formatting, search)
|
|
142
|
+
- `src/resources/` MCP resource templates
|
|
143
|
+
- `src/transport/` stdio + HTTP
|
|
144
|
+
- `tests/unit/` utilities
|
|
145
|
+
- `tests/integration/` tool behavior
|
|
146
|
+
- `tests/fixtures/` mocked CKAN API responses
|
|
147
|
+
|
|
148
|
+
## TypeScript Style
|
|
149
|
+
|
|
150
|
+
- Use strict typing (`tsconfig.json` has `strict: true`)
|
|
151
|
+
- Avoid `any` unless unavoidable or from CKAN payloads
|
|
152
|
+
- Prefer explicit return types for exported functions
|
|
153
|
+
- Use `type` aliases for structured objects
|
|
154
|
+
- Keep `noUnusedLocals` and `noUnusedParameters` clean
|
|
155
|
+
- ESM imports with `.js` extensions for local modules
|
|
156
|
+
|
|
157
|
+
## Import Conventions
|
|
158
|
+
|
|
159
|
+
- Use `import type` for type-only imports
|
|
160
|
+
- Group imports by kind: external, internal, types
|
|
161
|
+
- Use double quotes for strings
|
|
162
|
+
- Keep import paths relative and short
|
|
163
|
+
|
|
164
|
+
## Naming
|
|
165
|
+
|
|
166
|
+
- `camelCase` for vars/functions
|
|
167
|
+
- `PascalCase` for types/classes
|
|
168
|
+
- `UPPER_SNAKE_CASE` for constants
|
|
169
|
+
- Tool names match MCP tool id strings
|
|
170
|
+
|
|
171
|
+
## Error Handling
|
|
172
|
+
|
|
173
|
+
- Wrap tool handlers in `try/catch`
|
|
174
|
+
- Return `{ isError: true }` for MCP errors
|
|
175
|
+
- Include user-facing error text with context
|
|
176
|
+
- For HTTP errors, map to readable messages
|
|
177
|
+
- Preserve error cause when rethrowing
|
|
178
|
+
|
|
179
|
+
## Tool Responses
|
|
180
|
+
|
|
181
|
+
- Use `ResponseFormat` for markdown vs JSON
|
|
182
|
+
- Use `truncateText` for large payloads
|
|
183
|
+
- Keep JSON output pretty-printed
|
|
184
|
+
- Include `structuredContent` for JSON mode
|
|
185
|
+
|
|
186
|
+
## Testing Guidelines
|
|
187
|
+
|
|
188
|
+
- Tests use Vitest and `globals: true`
|
|
189
|
+
- Place new tests in `tests/unit` or `tests/integration`
|
|
190
|
+
- Follow AAA pattern: Arrange, Act, Assert
|
|
191
|
+
- Mock CKAN API via fixtures under `tests/fixtures`
|
|
192
|
+
- Name tests descriptively with expected behavior
|
|
193
|
+
|
|
194
|
+
## Configuration Notes
|
|
195
|
+
|
|
196
|
+
- Node engine: `>=18`
|
|
197
|
+
- Worker build command set in `wrangler.toml`
|
|
198
|
+
- Vitest coverage thresholds enforced in `vitest.config.ts`
|
|
199
|
+
|
|
200
|
+
## Change Hygiene
|
|
201
|
+
|
|
202
|
+
- Keep diffs minimal and focused
|
|
203
|
+
- Avoid unrelated refactors
|
|
204
|
+
- Update tests for behavior changes
|
|
205
|
+
- Avoid editing `dist/` (generated)
|
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 (179 tests - unit + integration)
|
|
45
45
|
npm test
|
|
46
46
|
|
|
47
47
|
# Watch mode for tests during development
|
|
@@ -73,8 +73,8 @@ npm run deploy # Deploy to Cloudflare Workers
|
|
|
73
73
|
The project uses **esbuild** for compilation and **vitest** for testing:
|
|
74
74
|
|
|
75
75
|
- **Build**: Ultra-fast builds (milliseconds instead of minutes)
|
|
76
|
-
- **Tests**:
|
|
77
|
-
- **Coverage**:
|
|
76
|
+
- **Tests**: 179 tests (unit + integration) with 100% success rate
|
|
77
|
+
- **Coverage**: ~39% overall (utils: 98%, tools: 15-20%) - available via vitest with v8 coverage engine
|
|
78
78
|
|
|
79
79
|
The `build:tsc` script is available as a fallback but can cause memory issues in some environments (particularly WSL). Always use `npm run build` which uses esbuild.
|
|
80
80
|
|
|
@@ -101,7 +101,7 @@ tests/
|
|
|
101
101
|
โโโ errors/ # Error scenario mocks
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
**Test Coverage**:
|
|
104
|
+
**Test Coverage**: 179 tests total (85 unit + 94 integration)
|
|
105
105
|
|
|
106
106
|
When making changes:
|
|
107
107
|
1. Run tests before committing: `npm test`
|
|
@@ -292,11 +292,14 @@ npm run test:watch
|
|
|
292
292
|
npm run test:coverage
|
|
293
293
|
```
|
|
294
294
|
|
|
295
|
-
|
|
296
|
-
|
|
295
|
+
Current test coverage: ~39% overall (utility modules: 98%, tool handlers: 15-20%).
|
|
296
|
+
|
|
297
|
+
Test suite includes:
|
|
298
|
+
- Unit tests for utility functions (formatting, HTTP, URI parsing, URL generation, search)
|
|
297
299
|
- Integration tests for MCP tools with mocked CKAN API responses
|
|
298
300
|
- Mock fixtures for CKAN API success and error scenarios
|
|
299
301
|
|
|
302
|
+
Coverage is strong for utility modules but needs improvement for tool handlers.
|
|
300
303
|
See `tests/README.md` for detailed testing guidelines and fixture structure.
|
|
301
304
|
|
|
302
305
|
### Manual Testing
|
|
@@ -338,8 +341,8 @@ To test with Claude Desktop, add the MCP configuration to the config file.
|
|
|
338
341
|
- Direct data access for datasets, resources, organizations
|
|
339
342
|
|
|
340
343
|
**v0.2.0 (2026-01-08)**: Comprehensive test suite
|
|
341
|
-
-
|
|
342
|
-
-
|
|
344
|
+
- 179 tests (unit + integration)
|
|
345
|
+
- ~39% code coverage (utils well-tested, tools improving)
|
|
343
346
|
|
|
344
347
|
**v0.1.0 (2026-01-08)**: Modular refactoring
|
|
345
348
|
- Restructured from monolithic file to 11 modules
|
package/LOG.md
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
# LOG
|
|
2
2
|
|
|
3
|
+
## 2026-01-11
|
|
4
|
+
|
|
5
|
+
### Version 0.4.9 - Security, Testing & Documentation
|
|
6
|
+
- **Security**: Updated @modelcontextprotocol/sdk from 1.25.1 to 1.25.2 (fixes HIGH severity ReDoS vulnerability)
|
|
7
|
+
- **Testing**: Added 49 new unit tests for package.ts scoring functions
|
|
8
|
+
- **Coverage**: Improved from 37.33% to 38.63% (package.ts: 12.5% to 15%)
|
|
9
|
+
- **Total tests**: 179 tests (all passing, +49 from 130)
|
|
10
|
+
- **Documentation**: Corrected test coverage claims (was "113 tests, 97%+" now accurate "179 tests, ~39%")
|
|
11
|
+
- **Deployment**: Added npm audit check to DEPLOYMENT.md
|
|
12
|
+
- **Files modified**: package.json, src/server.ts, src/worker.ts, README.md, CLAUDE.md, docs/DEPLOYMENT.md
|
|
13
|
+
- **New file**: tests/unit/package-scoring.test.ts
|
|
14
|
+
- **No breaking changes**: All existing functionality preserved
|
|
15
|
+
|
|
16
|
+
### Test improvements - package scoring functions
|
|
17
|
+
- **Added**: 49 new unit tests for package.ts scoring functions
|
|
18
|
+
- **Coverage improvement**: package.ts from 12.5% to 15%
|
|
19
|
+
- **Overall coverage**: 37.33% to 38.63%
|
|
20
|
+
- **Total tests**: 130 to 179 tests (all passing)
|
|
21
|
+
- **New test file**: tests/unit/package-scoring.test.ts
|
|
22
|
+
- **Functions tested**:
|
|
23
|
+
- extractQueryTerms (10 tests)
|
|
24
|
+
- escapeRegExp (6 tests)
|
|
25
|
+
- textMatchesTerms (10 tests)
|
|
26
|
+
- scoreTextField (6 tests)
|
|
27
|
+
- scoreDatasetRelevance (17 tests with edge cases)
|
|
28
|
+
- **Exports**: Made internal functions testable (extractQueryTerms, escapeRegExp, textMatchesTerms, scoreTextField)
|
|
29
|
+
- **Impact**: Better coverage of dataset relevance scoring logic
|
|
30
|
+
|
|
31
|
+
### Documentation corrections - test coverage accuracy
|
|
32
|
+
- **Fix**: Corrected test coverage claims in README.md and CLAUDE.md
|
|
33
|
+
- **Previous claim**: "113 tests, 97%+ coverage"
|
|
34
|
+
- **Actual values**: 130 tests passing, ~37% overall coverage
|
|
35
|
+
- Utility modules: 98% coverage (excellent)
|
|
36
|
+
- Tool handlers: 12-20% coverage (needs improvement)
|
|
37
|
+
- **Impact**: Documentation now accurately reflects project state
|
|
38
|
+
- **Files modified**: README.md, CLAUDE.md
|
|
39
|
+
|
|
40
|
+
### Documentation enhancement - deployment security
|
|
41
|
+
- **Added**: npm audit check to DEPLOYMENT.md (Step 4.5)
|
|
42
|
+
- **Added**: Security audit to pre-release checklist
|
|
43
|
+
- **Recommendation**: Always run `npm audit` before production deployment
|
|
44
|
+
|
|
45
|
+
### Security fix - MCP SDK update
|
|
46
|
+
- **Fix**: Update @modelcontextprotocol/sdk from 1.25.1 to 1.25.2
|
|
47
|
+
- **Reason**: Resolves HIGH severity ReDoS vulnerability (GHSA-8r9q-7v3j-jr4g)
|
|
48
|
+
- **Tests**: All 130 tests passing
|
|
49
|
+
- **Audit**: 0 vulnerabilities
|
|
50
|
+
|
|
3
51
|
## 2026-01-10
|
|
4
52
|
|
|
5
53
|
### Version 0.4.8 - Organization list fallback
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ MCP (Model Context Protocol) server for interacting with CKAN-based open data po
|
|
|
14
14
|
- ๐จ Output in Markdown or JSON format
|
|
15
15
|
- โก Pagination and faceting support
|
|
16
16
|
- ๐ MCP Resource Templates for direct data access
|
|
17
|
-
- ๐งช
|
|
17
|
+
- ๐งช Test suite with 179 tests (100% passing)
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
20
20
|
|
|
@@ -36,7 +36,7 @@ npm install
|
|
|
36
36
|
# Build with esbuild (fast, ~4ms)
|
|
37
37
|
npm run build
|
|
38
38
|
|
|
39
|
-
# Run tests (
|
|
39
|
+
# Run tests (179 tests)
|
|
40
40
|
npm test
|
|
41
41
|
```
|
|
42
42
|
|
|
@@ -204,7 +204,7 @@ ckan://data.gov/organization/sample-org
|
|
|
204
204
|
|
|
205
205
|
## Usage Examples
|
|
206
206
|
|
|
207
|
-
### Search datasets on dati.gov.it
|
|
207
|
+
### Search datasets on dati.gov.it (natural language: "search for population datasets")
|
|
208
208
|
|
|
209
209
|
```typescript
|
|
210
210
|
ckan_package_search({
|
|
@@ -214,7 +214,7 @@ ckan_package_search({
|
|
|
214
214
|
})
|
|
215
215
|
```
|
|
216
216
|
|
|
217
|
-
### Force text-field parser for long OR queries
|
|
217
|
+
### Force text-field parser for long OR queries (natural language: "find hotel or accommodation datasets")
|
|
218
218
|
|
|
219
219
|
```typescript
|
|
220
220
|
ckan_package_search({
|
|
@@ -225,7 +225,7 @@ ckan_package_search({
|
|
|
225
225
|
})
|
|
226
226
|
```
|
|
227
227
|
|
|
228
|
-
### Rank datasets by relevance
|
|
228
|
+
### Rank datasets by relevance (natural language: "find most relevant datasets about urban mobility")
|
|
229
229
|
|
|
230
230
|
```typescript
|
|
231
231
|
ckan_find_relevant_datasets({
|
|
@@ -235,7 +235,7 @@ ckan_find_relevant_datasets({
|
|
|
235
235
|
})
|
|
236
236
|
```
|
|
237
237
|
|
|
238
|
-
### Filter by organization
|
|
238
|
+
### Filter by organization (natural language: "show recent datasets from Sicilian Region")
|
|
239
239
|
|
|
240
240
|
```typescript
|
|
241
241
|
ckan_package_search({
|
|
@@ -245,7 +245,7 @@ ckan_package_search({
|
|
|
245
245
|
})
|
|
246
246
|
```
|
|
247
247
|
|
|
248
|
-
### Search organizations with wildcard
|
|
248
|
+
### Search organizations with wildcard (natural language: "find all organizations with health/salute in name")
|
|
249
249
|
|
|
250
250
|
```typescript
|
|
251
251
|
// Find all organizations containing "salute" in the name
|
|
@@ -258,7 +258,7 @@ ckan_package_search({
|
|
|
258
258
|
})
|
|
259
259
|
```
|
|
260
260
|
|
|
261
|
-
### Get statistics with faceting
|
|
261
|
+
### Get statistics with faceting (natural language: "show statistics by organization, tags and format")
|
|
262
262
|
|
|
263
263
|
```typescript
|
|
264
264
|
ckan_package_search({
|
|
@@ -287,7 +287,7 @@ ckan_group_search({
|
|
|
287
287
|
})
|
|
288
288
|
```
|
|
289
289
|
|
|
290
|
-
### DataStore Query
|
|
290
|
+
### DataStore Query (natural language: "query tabular data filtering by region and year")
|
|
291
291
|
|
|
292
292
|
```typescript
|
|
293
293
|
ckan_datastore_search({
|
|
@@ -299,7 +299,7 @@ ckan_datastore_search({
|
|
|
299
299
|
})
|
|
300
300
|
```
|
|
301
301
|
|
|
302
|
-
### DataStore SQL Query
|
|
302
|
+
### DataStore SQL Query (natural language: "count records by country with SQL")
|
|
303
303
|
|
|
304
304
|
```typescript
|
|
305
305
|
ckan_datastore_search_sql({
|
|
@@ -365,7 +365,7 @@ fq: "metadata_modified:[2023-01-01T00:00:00Z TO *]"
|
|
|
365
365
|
|
|
366
366
|
These real-world examples demonstrate powerful Solr query combinations tested on the Italian open data portal (dati.gov.it):
|
|
367
367
|
|
|
368
|
-
#### 1. Fuzzy Search + Date Math + Boosting
|
|
368
|
+
#### 1. Fuzzy Search + Date Math + Boosting (natural language: "find healthcare datasets modified in last 6 months")
|
|
369
369
|
|
|
370
370
|
Find healthcare datasets (tolerating spelling errors) modified in the last 6 months, prioritizing title matches:
|
|
371
371
|
|
|
@@ -387,7 +387,7 @@ ckan_package_search({
|
|
|
387
387
|
|
|
388
388
|
**Results**: 871 datasets including hospital units, healthcare organizations, medical services
|
|
389
389
|
|
|
390
|
-
#### 2. Proximity Search + Complex Boolean
|
|
390
|
+
#### 2. Proximity Search + Complex Boolean (natural language: "find air pollution datasets excluding water")
|
|
391
391
|
|
|
392
392
|
Environmental datasets where "inquinamento" and "aria" (air pollution) appear close together, excluding water-related datasets:
|
|
393
393
|
|
|
@@ -409,7 +409,7 @@ ckan_package_search({
|
|
|
409
409
|
|
|
410
410
|
**Results**: 306 datasets, primarily air quality monitoring from Milan (44) and Palermo (161), formats: XML (150), CSV (124), JSON (76)
|
|
411
411
|
|
|
412
|
-
#### 3. Wildcard + Field Existence + Range Queries
|
|
412
|
+
#### 3. Wildcard + Field Existence + Range Queries (natural language: "regional datasets with many resources from last year")
|
|
413
413
|
|
|
414
414
|
Regional datasets with at least 5 resources, published in the last year:
|
|
415
415
|
|
|
@@ -432,7 +432,7 @@ ckan_package_search({
|
|
|
432
432
|
|
|
433
433
|
**Results**: 5,318 datasets, top contributors: Lombardy (3,012), Tuscany (1,151), Puglia (460)
|
|
434
434
|
|
|
435
|
-
#### 4. Date Ranges + Exclusive Bounds
|
|
435
|
+
#### 4. Date Ranges + Exclusive Bounds (natural language: "ISTAT datasets with 10-50 resources from specific period")
|
|
436
436
|
|
|
437
437
|
ISTAT datasets with moderate resource count (10-50), modified in specific date range:
|
|
438
438
|
|
|
@@ -500,7 +500,7 @@ ckan-mcp-server/
|
|
|
500
500
|
โ โโโ transport/
|
|
501
501
|
โ โโโ stdio.ts # Stdio transport
|
|
502
502
|
โ โโโ http.ts # HTTP transport
|
|
503
|
-
โโโ tests/ # Test suite (
|
|
503
|
+
โโโ tests/ # Test suite (179 tests)
|
|
504
504
|
โโโ dist/ # Compiled files (generated)
|
|
505
505
|
โโโ package.json
|
|
506
506
|
โโโ README.md
|
|
@@ -523,12 +523,14 @@ npm run test:watch
|
|
|
523
523
|
npm run test:coverage
|
|
524
524
|
```
|
|
525
525
|
|
|
526
|
-
|
|
526
|
+
Current test coverage: ~39% (utils: 98%, tools: 15-20%).
|
|
527
527
|
|
|
528
|
-
|
|
528
|
+
Test suite includes:
|
|
529
|
+
- Unit tests for utility functions (formatting, HTTP, URI parsing, URL generation)
|
|
529
530
|
- Integration tests for MCP tools with mocked CKAN API responses
|
|
530
531
|
- Mock fixtures for CKAN API success and error scenarios
|
|
531
532
|
|
|
533
|
+
Coverage is higher for utility modules and lower for tool handlers.
|
|
532
534
|
See `tests/README.md` for detailed testing guidelines.
|
|
533
535
|
|
|
534
536
|
### Build
|