@aborruso/ckan-mcp-server 0.4.17 → 0.4.18
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/LOG.md +59 -0
- package/README.md +104 -34
- package/dist/index.js +161 -45
- package/dist/worker.js +42 -42
- package/package.json +12 -1
- package/.devin/wiki.json +0 -273
- package/CLAUDE.md +0 -398
- package/PRD.md +0 -999
- package/REFACTORING.md +0 -238
- package/examples/langgraph/01_basic_workflow.py +0 -277
- package/examples/langgraph/02_data_exploration.py +0 -366
- package/examples/langgraph/README.md +0 -719
- package/examples/langgraph/metadata_quality.py +0 -299
- package/examples/langgraph/requirements.txt +0 -12
- package/examples/langgraph/setup.sh +0 -32
- package/examples/langgraph/test_setup.py +0 -106
- package/openspec/AGENTS.md +0 -456
- package/openspec/changes/add-ckan-analyze-dataset-structure/proposal.md +0 -17
- package/openspec/changes/add-ckan-analyze-dataset-structure/specs/ckan-insights/spec.md +0 -7
- package/openspec/changes/add-ckan-analyze-dataset-structure/tasks.md +0 -6
- package/openspec/changes/add-ckan-analyze-dataset-updates/proposal.md +0 -17
- package/openspec/changes/add-ckan-analyze-dataset-updates/specs/ckan-insights/spec.md +0 -7
- package/openspec/changes/add-ckan-analyze-dataset-updates/tasks.md +0 -6
- package/openspec/changes/add-ckan-audit-tool/proposal.md +0 -17
- package/openspec/changes/add-ckan-audit-tool/specs/ckan-insights/spec.md +0 -7
- package/openspec/changes/add-ckan-audit-tool/tasks.md +0 -6
- package/openspec/changes/add-ckan-dataset-insights/proposal.md +0 -17
- package/openspec/changes/add-ckan-dataset-insights/specs/ckan-insights/spec.md +0 -7
- package/openspec/changes/add-ckan-dataset-insights/tasks.md +0 -6
- package/openspec/changes/add-ckan-host-allowlist-env/design.md +0 -38
- package/openspec/changes/add-ckan-host-allowlist-env/proposal.md +0 -16
- package/openspec/changes/add-ckan-host-allowlist-env/specs/ckan-request-allowlist/spec.md +0 -15
- package/openspec/changes/add-ckan-host-allowlist-env/specs/cloudflare-deployment/spec.md +0 -11
- package/openspec/changes/add-ckan-host-allowlist-env/tasks.md +0 -12
- package/openspec/changes/add-escape-text-query/proposal.md +0 -12
- package/openspec/changes/add-escape-text-query/specs/ckan-search/spec.md +0 -11
- package/openspec/changes/add-escape-text-query/tasks.md +0 -8
- package/openspec/changes/add-mqa-quality-tool/proposal.md +0 -21
- package/openspec/changes/add-mqa-quality-tool/specs/ckan-quality/spec.md +0 -71
- package/openspec/changes/add-mqa-quality-tool/tasks.md +0 -29
- package/openspec/changes/archive/2026-01-08-add-mcp-resources/design.md +0 -115
- package/openspec/changes/archive/2026-01-08-add-mcp-resources/proposal.md +0 -52
- package/openspec/changes/archive/2026-01-08-add-mcp-resources/specs/mcp-resources/spec.md +0 -92
- package/openspec/changes/archive/2026-01-08-add-mcp-resources/tasks.md +0 -56
- package/openspec/changes/archive/2026-01-08-expand-test-coverage-specs/design.md +0 -355
- package/openspec/changes/archive/2026-01-08-expand-test-coverage-specs/proposal.md +0 -161
- package/openspec/changes/archive/2026-01-08-expand-test-coverage-specs/tasks.md +0 -162
- package/openspec/changes/archive/2026-01-08-translate-project-to-english/proposal.md +0 -115
- package/openspec/changes/archive/2026-01-08-translate-project-to-english/specs/documentation-language/spec.md +0 -32
- package/openspec/changes/archive/2026-01-08-translate-project-to-english/tasks.md +0 -115
- package/openspec/changes/archive/2026-01-10-add-ckan-find-relevant-datasets/proposal.md +0 -17
- package/openspec/changes/archive/2026-01-10-add-ckan-find-relevant-datasets/specs/ckan-insights/spec.md +0 -7
- package/openspec/changes/archive/2026-01-10-add-ckan-find-relevant-datasets/tasks.md +0 -6
- package/openspec/changes/archive/2026-01-10-add-cloudflare-workers/design.md +0 -734
- package/openspec/changes/archive/2026-01-10-add-cloudflare-workers/proposal.md +0 -183
- package/openspec/changes/archive/2026-01-10-add-cloudflare-workers/specs/cloudflare-deployment/spec.md +0 -389
- package/openspec/changes/archive/2026-01-10-add-cloudflare-workers/tasks.md +0 -519
- package/openspec/changes/archive/2026-01-15-add-mcp-prompts/proposal.md +0 -13
- package/openspec/changes/archive/2026-01-15-add-mcp-prompts/specs/mcp-prompts/spec.md +0 -22
- package/openspec/changes/archive/2026-01-15-add-mcp-prompts/tasks.md +0 -10
- package/openspec/changes/archive/2026-01-15-add-mcp-resource-filters/proposal.md +0 -13
- package/openspec/changes/archive/2026-01-15-add-mcp-resource-filters/specs/mcp-resources/spec.md +0 -38
- package/openspec/changes/archive/2026-01-15-add-mcp-resource-filters/tasks.md +0 -10
- package/openspec/changes/archive/2026-01-19-update-repo-owner-ondata/proposal.md +0 -13
- package/openspec/changes/archive/2026-01-19-update-repo-owner-ondata/specs/repository-metadata/spec.md +0 -14
- package/openspec/changes/archive/2026-01-19-update-repo-owner-ondata/tasks.md +0 -12
- package/openspec/changes/archive/2026-01-19-update-search-parser-config/proposal.md +0 -13
- package/openspec/changes/archive/2026-01-19-update-search-parser-config/specs/ckan-insights/spec.md +0 -11
- package/openspec/changes/archive/2026-01-19-update-search-parser-config/specs/ckan-search/spec.md +0 -11
- package/openspec/changes/archive/2026-01-19-update-search-parser-config/tasks.md +0 -6
- package/openspec/changes/archive/add-automated-tests/design.md +0 -324
- package/openspec/changes/archive/add-automated-tests/proposal.md +0 -167
- package/openspec/changes/archive/add-automated-tests/specs/automated-testing/spec.md +0 -143
- package/openspec/changes/archive/add-automated-tests/tasks.md +0 -132
- package/openspec/project.md +0 -115
- package/openspec/specs/ckan-insights/spec.md +0 -23
- package/openspec/specs/ckan-search/spec.md +0 -16
- package/openspec/specs/cloudflare-deployment/spec.md +0 -344
- package/openspec/specs/documentation-language/spec.md +0 -32
- package/openspec/specs/mcp-prompts/spec.md +0 -26
- package/openspec/specs/mcp-resources/spec.md +0 -120
- package/openspec/specs/repository-metadata/spec.md +0 -19
- package/private/commenti-privati.yaml +0 -14
- package/testo.md +0 -12
- package/web-gui/PRD.md +0 -158
- package/web-gui/public/index.html +0 -883
- package/wrangler.toml +0 -6
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
## 1. Implementation
|
|
2
|
-
- [ ] Add allowlist parsing utility for `ALLOWED_CKAN_HOSTS` (comma-separated hostnames, case-insensitive, trim whitespace).
|
|
3
|
-
- [ ] Enforce allowlist for all CKAN requests (tools and resource templates) with clear error messaging.
|
|
4
|
-
- [ ] Ensure allowlist applies to both Node and Workers runtimes.
|
|
5
|
-
|
|
6
|
-
## 2. Configuration
|
|
7
|
-
- [ ] Add `ALLOWED_CKAN_HOSTS` to `wrangler.toml` with example values.
|
|
8
|
-
- [ ] Update docs/README to describe the env var and behavior (optional if required by spec).
|
|
9
|
-
|
|
10
|
-
## 3. Tests
|
|
11
|
-
- [ ] Add unit tests for allowlist parsing and validation.
|
|
12
|
-
- [ ] Add tool/resource tests verifying rejection for non-allowed hosts when env var is set.
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# Change: Escape text-field query wrapping in search parser
|
|
2
|
-
|
|
3
|
-
## Why
|
|
4
|
-
Wrapping arbitrary user input in `text:(...)` without escaping allows query parser errors or unintended semantics when the input contains Solr/Lucene metacharacters (e.g., `"` or `)`).
|
|
5
|
-
|
|
6
|
-
## What Changes
|
|
7
|
-
- Escape Solr/Lucene special characters before wrapping user input in `text:(...)`.
|
|
8
|
-
- Add tests to confirm escaped output and prevent regressions.
|
|
9
|
-
|
|
10
|
-
## Impact
|
|
11
|
-
- Affected specs: `ckan-search`
|
|
12
|
-
- Affected code: `src/utils/search.ts`, package search tool behavior, related tests.
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
## MODIFIED Requirements
|
|
2
|
-
### Requirement: Package search parser override
|
|
3
|
-
The system SHALL support a per-portal default and a per-request override to force package search queries through the `text` field when needed, and SHALL escape Solr/Lucene special characters when wrapping queries in `text:(...)`.
|
|
4
|
-
|
|
5
|
-
#### Scenario: Portal default applies
|
|
6
|
-
- **WHEN** a portal is configured to force the text-field parser
|
|
7
|
-
- **THEN** `ckan_package_search` uses `text:(...)` for non-fielded queries by default with escaped query content
|
|
8
|
-
|
|
9
|
-
#### Scenario: Request override applies
|
|
10
|
-
- **WHEN** a client explicitly requests the text-field parser
|
|
11
|
-
- **THEN** `ckan_package_search` uses `text:(...)` regardless of portal defaults with escaped query content
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
## 1. Implementation
|
|
2
|
-
- [x] Add a Solr/Lucene escaping helper for text-field queries.
|
|
3
|
-
- [x] Apply escaping when `resolveSearchQuery` forces `text:(...)`.
|
|
4
|
-
- [x] Ensure behavior is unchanged when not forcing the text parser.
|
|
5
|
-
|
|
6
|
-
## 2. Tests
|
|
7
|
-
- [x] Add unit tests for escaping behavior (quotes, parentheses, backslashes, colons).
|
|
8
|
-
- [x] Add tests to cover `resolveSearchQuery` effectiveQuery output with forced text parser.
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Change: Add MQA Quality Score Tool for dati.gov.it
|
|
2
|
-
|
|
3
|
-
## Why
|
|
4
|
-
Datasets on dati.gov.it display quality scores (Eccellente, Buono, etc.) calculated by data.europa.eu's MQA (Metadata Quality Assurance) system. Currently there's no way to access these quality metrics through the MCP server, limiting users' ability to evaluate dataset quality programmatically.
|
|
5
|
-
|
|
6
|
-
## What Changes
|
|
7
|
-
- Add `ckan_get_mqa_quality` tool for retrieving quality metrics from data.europa.eu
|
|
8
|
-
- Tool works only with dati.gov.it server (validated at runtime)
|
|
9
|
-
- Fetches dataset identifier from CKAN, then queries MQA API
|
|
10
|
-
- Returns quality score and detailed metrics (accessibility, reusability, interoperability, findability)
|
|
11
|
-
- Supports both markdown and JSON output formats
|
|
12
|
-
|
|
13
|
-
## Impact
|
|
14
|
-
- Affected specs: New capability `ckan-quality`
|
|
15
|
-
- Affected code:
|
|
16
|
-
- New file: `src/tools/quality.ts` (tool handler)
|
|
17
|
-
- New file: `tests/integration/quality.test.ts` (tests with mocked responses)
|
|
18
|
-
- New file: `tests/fixtures/responses/mqa-quality.json` (mock data)
|
|
19
|
-
- Modified: `src/server.ts` (register new tool)
|
|
20
|
-
- Modified: `README.md` (document new tool)
|
|
21
|
-
- Modified: `EXAMPLES.md` (add usage examples)
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
## ADDED Requirements
|
|
2
|
-
|
|
3
|
-
### Requirement: MQA Quality Score Retrieval
|
|
4
|
-
The system SHALL provide a tool to retrieve MQA (Metadata Quality Assurance) quality metrics from data.europa.eu for datasets published on dati.gov.it.
|
|
5
|
-
|
|
6
|
-
#### Scenario: Successful quality score retrieval
|
|
7
|
-
- **GIVEN** a valid dataset ID from dati.gov.it
|
|
8
|
-
- **WHEN** user requests quality metrics
|
|
9
|
-
- **THEN** system SHALL fetch identifier field from CKAN package_show
|
|
10
|
-
- **AND** system SHALL query data.europa.eu MQA API
|
|
11
|
-
- **AND** system SHALL return quality score and detailed metrics (accessibility, reusability, interoperability, findability)
|
|
12
|
-
|
|
13
|
-
#### Scenario: Identifier fallback to name
|
|
14
|
-
- **GIVEN** a dataset with empty identifier field
|
|
15
|
-
- **WHEN** user requests quality metrics
|
|
16
|
-
- **THEN** system SHALL use the name field as fallback identifier for MQA API query
|
|
17
|
-
|
|
18
|
-
#### Scenario: Dataset not found
|
|
19
|
-
- **GIVEN** an invalid or non-existent dataset ID
|
|
20
|
-
- **WHEN** user requests quality metrics
|
|
21
|
-
- **THEN** system SHALL return clear error message indicating dataset not found
|
|
22
|
-
|
|
23
|
-
#### Scenario: MQA API unavailable
|
|
24
|
-
- **GIVEN** data.europa.eu MQA API is unavailable or returns error
|
|
25
|
-
- **WHEN** user requests quality metrics
|
|
26
|
-
- **THEN** system SHALL return clear error message indicating MQA service unavailability
|
|
27
|
-
|
|
28
|
-
### Requirement: Server Validation
|
|
29
|
-
The system SHALL restrict MQA quality queries to dati.gov.it server only.
|
|
30
|
-
|
|
31
|
-
#### Scenario: Valid dati.gov.it server
|
|
32
|
-
- **GIVEN** server_url is "https://www.dati.gov.it/opendata" or "https://dati.gov.it/opendata"
|
|
33
|
-
- **WHEN** user requests quality metrics
|
|
34
|
-
- **THEN** system SHALL proceed with MQA query
|
|
35
|
-
|
|
36
|
-
#### Scenario: Invalid server URL
|
|
37
|
-
- **GIVEN** server_url is not dati.gov.it (e.g., "https://catalog.data.gov")
|
|
38
|
-
- **WHEN** user requests quality metrics
|
|
39
|
-
- **THEN** system SHALL reject request with error message explaining MQA is only available for dati.gov.it
|
|
40
|
-
|
|
41
|
-
### Requirement: Output Formats
|
|
42
|
-
The system SHALL support both markdown and JSON output formats for quality metrics.
|
|
43
|
-
|
|
44
|
-
#### Scenario: Markdown format (default)
|
|
45
|
-
- **GIVEN** user does not specify response_format or specifies "markdown"
|
|
46
|
-
- **WHEN** quality metrics are retrieved
|
|
47
|
-
- **THEN** system SHALL return human-readable markdown with:
|
|
48
|
-
- Overall quality score
|
|
49
|
-
- Breakdown by dimension (accessibility, reusability, interoperability, findability)
|
|
50
|
-
- Key findings and recommendations
|
|
51
|
-
|
|
52
|
-
#### Scenario: JSON format
|
|
53
|
-
- **GIVEN** user specifies response_format as "json"
|
|
54
|
-
- **WHEN** quality metrics are retrieved
|
|
55
|
-
- **THEN** system SHALL return complete MQA API response as structured JSON
|
|
56
|
-
|
|
57
|
-
### Requirement: Tool Parameters
|
|
58
|
-
The system SHALL accept the following parameters for the MQA quality tool:
|
|
59
|
-
- server_url (required): Base URL of dati.gov.it portal
|
|
60
|
-
- dataset_id (required): Dataset ID or name
|
|
61
|
-
- response_format (optional): "markdown" (default) or "json"
|
|
62
|
-
|
|
63
|
-
#### Scenario: Minimal parameters
|
|
64
|
-
- **GIVEN** user provides only server_url and dataset_id
|
|
65
|
-
- **WHEN** tool is invoked
|
|
66
|
-
- **THEN** system SHALL use default markdown format
|
|
67
|
-
|
|
68
|
-
#### Scenario: All parameters specified
|
|
69
|
-
- **GIVEN** user provides server_url, dataset_id, and response_format
|
|
70
|
-
- **WHEN** tool is invoked
|
|
71
|
-
- **THEN** system SHALL use specified format for output
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# Implementation Tasks
|
|
2
|
-
|
|
3
|
-
## 1. Core Implementation
|
|
4
|
-
- [x] 1.1 Create `src/tools/quality.ts` with `ckan_get_mqa_quality` tool handler
|
|
5
|
-
- [x] 1.2 Implement server URL validation (dati.gov.it only)
|
|
6
|
-
- [x] 1.3 Add CKAN package_show call to extract identifier field
|
|
7
|
-
- [x] 1.4 Add MQA API client (https://data.europa.eu/api/mqa/cache/datasets/{id})
|
|
8
|
-
- [x] 1.5 Implement markdown and JSON formatters for quality metrics
|
|
9
|
-
- [x] 1.6 Register tool in `src/server.ts`
|
|
10
|
-
|
|
11
|
-
## 2. Testing
|
|
12
|
-
- [x] 2.1 Create mock fixtures for CKAN package_show response
|
|
13
|
-
- [x] 2.2 Create mock fixtures for MQA API response
|
|
14
|
-
- [x] 2.3 Write integration tests for successful quality retrieval
|
|
15
|
-
- [x] 2.4 Write tests for error scenarios (invalid server, dataset not found, MQA API unavailable)
|
|
16
|
-
- [x] 2.5 Write tests for fallback from identifier to name field
|
|
17
|
-
- [x] 2.6 Verify test coverage matches project standards
|
|
18
|
-
|
|
19
|
-
## 3. Documentation
|
|
20
|
-
- [x] 3.1 Add tool description to README.md
|
|
21
|
-
- [x] 3.2 Add usage examples to EXAMPLES.md
|
|
22
|
-
- [x] 3.3 Document server restriction (dati.gov.it only)
|
|
23
|
-
- [x] 3.4 Document quality metrics structure (score, accessibility, reusability, interoperability, findability)
|
|
24
|
-
|
|
25
|
-
## 4. Validation
|
|
26
|
-
- [x] 4.1 Run full test suite (npm test) - 212 tests passing
|
|
27
|
-
- [x] 4.2 Test manually with real dati.gov.it dataset
|
|
28
|
-
- [x] 4.3 Verify error handling for non-dati.gov.it servers
|
|
29
|
-
- [x] 4.4 Build project successfully (npm run build)
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
# Design: MCP Resource Templates
|
|
2
|
-
|
|
3
|
-
## Context
|
|
4
|
-
|
|
5
|
-
MCP protocol supports two primitives:
|
|
6
|
-
- **Tools**: Functions that perform actions (current implementation)
|
|
7
|
-
- **Resources**: Data that can be read directly (to be added)
|
|
8
|
-
|
|
9
|
-
The `@modelcontextprotocol/sdk` provides `server.registerResourceTemplate()` for dynamic resources with URI templates.
|
|
10
|
-
|
|
11
|
-
## Goals / Non-Goals
|
|
12
|
-
|
|
13
|
-
### Goals
|
|
14
|
-
- Expose CKAN data as MCP resources using `ckan://` URI scheme
|
|
15
|
-
- Support dataset, resource, and organization access
|
|
16
|
-
- Reuse existing `makeCkanRequest()` for CKAN API calls
|
|
17
|
-
- Maintain consistency with tool output formats
|
|
18
|
-
|
|
19
|
-
### Non-Goals
|
|
20
|
-
- Write operations (resources are read-only by design)
|
|
21
|
-
- Caching implementation (defer to future enhancement)
|
|
22
|
-
- Authentication support (public endpoints only, same as tools)
|
|
23
|
-
- Real-time subscriptions (defer to future enhancement)
|
|
24
|
-
|
|
25
|
-
## Decisions
|
|
26
|
-
|
|
27
|
-
### URI Scheme Design
|
|
28
|
-
|
|
29
|
-
**Decision**: Use `ckan://{server}/type/{id}` pattern
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
ckan://dati.gov.it/dataset/vaccini-covid
|
|
33
|
-
ckan://data.gov/resource/abc-123
|
|
34
|
-
ckan://demo.ckan.org/organization/sample-org
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
**Rationale**:
|
|
38
|
-
- Server in hostname position enables multi-server support
|
|
39
|
-
- Type in path makes intent clear
|
|
40
|
-
- ID as final segment matches REST conventions
|
|
41
|
-
|
|
42
|
-
**Alternatives considered**:
|
|
43
|
-
1. `ckan://dataset/{server}/{id}` - rejected: server as path segment is unusual
|
|
44
|
-
2. `ckan+https://{server}/...` - rejected: overly complex
|
|
45
|
-
3. Query parameters `ckan://data?server=...&id=...` - rejected: less readable
|
|
46
|
-
|
|
47
|
-
### Module Structure
|
|
48
|
-
|
|
49
|
-
**Decision**: Create `src/resources/` directory with one file per resource type
|
|
50
|
-
|
|
51
|
-
```
|
|
52
|
-
src/resources/
|
|
53
|
-
├── index.ts # Export registerAllResources()
|
|
54
|
-
├── dataset.ts # ckan://{server}/dataset/{id}
|
|
55
|
-
├── resource.ts # ckan://{server}/resource/{id}
|
|
56
|
-
└── organization.ts # ckan://{server}/organization/{name}
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
**Rationale**: Mirrors existing `src/tools/` structure for consistency.
|
|
60
|
-
|
|
61
|
-
### URI Parsing
|
|
62
|
-
|
|
63
|
-
**Decision**: Extract server from URI hostname, type and ID from path
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
function parseResourceUri(uri: URL): { server: string; type: string; id: string } {
|
|
67
|
-
const server = uri.hostname;
|
|
68
|
-
const [, type, id] = uri.pathname.split('/');
|
|
69
|
-
return { server: `https://${server}`, type, id };
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
**Rationale**: Simple parsing, assumes HTTPS (most CKAN servers use it).
|
|
74
|
-
|
|
75
|
-
### Response Format
|
|
76
|
-
|
|
77
|
-
**Decision**: Return JSON by default (no markdown option for resources)
|
|
78
|
-
|
|
79
|
-
**Rationale**:
|
|
80
|
-
- Resources are meant for programmatic access
|
|
81
|
-
- LLMs can interpret JSON directly
|
|
82
|
-
- Keeps implementation simple
|
|
83
|
-
- Tools still support markdown for interactive use
|
|
84
|
-
|
|
85
|
-
## Risks / Trade-offs
|
|
86
|
-
|
|
87
|
-
| Risk | Mitigation |
|
|
88
|
-
|------|------------|
|
|
89
|
-
| SDK API changes | Pin SDK version, test before updates |
|
|
90
|
-
| URI parsing edge cases | Validate URIs before processing |
|
|
91
|
-
| Large responses | Apply existing `CHARACTER_LIMIT` truncation |
|
|
92
|
-
| Server unreachable | Same error handling as tools |
|
|
93
|
-
|
|
94
|
-
## Migration Plan
|
|
95
|
-
|
|
96
|
-
1. Add resources alongside existing tools (no breaking changes)
|
|
97
|
-
2. Resources are additive - tools remain fully functional
|
|
98
|
-
3. No migration needed for existing users
|
|
99
|
-
|
|
100
|
-
## Implementation Sequence
|
|
101
|
-
|
|
102
|
-
1. Create `src/resources/` directory structure
|
|
103
|
-
2. Implement URI parsing utility
|
|
104
|
-
3. Implement dataset resource template
|
|
105
|
-
4. Implement resource resource template
|
|
106
|
-
5. Implement organization resource template
|
|
107
|
-
6. Register resources in `src/index.ts`
|
|
108
|
-
7. Add tests for resource handlers
|
|
109
|
-
8. Update documentation
|
|
110
|
-
|
|
111
|
-
## Open Questions
|
|
112
|
-
|
|
113
|
-
1. Should resources support `response_format` parameter like tools?
|
|
114
|
-
2. Should we add `ckan://{server}/search?q=...` for search results as resource?
|
|
115
|
-
3. How to handle CKAN servers that require `www.` prefix (e.g., dati.gov.it)?
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
# Change: Add MCP Resource Templates
|
|
2
|
-
|
|
3
|
-
## Why
|
|
4
|
-
|
|
5
|
-
MCP has two primitives for exposing data: **Tools** (functions) and **Resources** (data). Currently we only expose tools. Adding resources enables:
|
|
6
|
-
|
|
7
|
-
1. Direct data access without tool calls
|
|
8
|
-
2. Native caching and subscription support
|
|
9
|
-
3. Better LLM context injection
|
|
10
|
-
4. Alignment with MCP best practices (see Data.gov MCP server pattern)
|
|
11
|
-
|
|
12
|
-
## What Changes
|
|
13
|
-
|
|
14
|
-
- Add MCP Resource Templates using RFC 6570 URI syntax
|
|
15
|
-
- Implement `ckan://` URI scheme for dataset and resource access
|
|
16
|
-
- Create new module `src/resources/` for resource handlers
|
|
17
|
-
- Register resources alongside existing tools
|
|
18
|
-
|
|
19
|
-
**New URI templates**:
|
|
20
|
-
- `ckan://{server}/dataset/{id}` - Dataset metadata
|
|
21
|
-
- `ckan://{server}/resource/{id}` - Resource metadata and download URL
|
|
22
|
-
- `ckan://{server}/organization/{name}` - Organization details
|
|
23
|
-
|
|
24
|
-
## Impact
|
|
25
|
-
|
|
26
|
-
- Affected specs: New capability `mcp-resources`
|
|
27
|
-
- Affected code:
|
|
28
|
-
- `src/index.ts` - import and register resources
|
|
29
|
-
- `src/resources/` - new directory with resource handlers
|
|
30
|
-
- `src/utils/http.ts` - may need minor adjustments
|
|
31
|
-
- No breaking changes to existing tools
|
|
32
|
-
- Dependencies: No new dependencies required
|
|
33
|
-
|
|
34
|
-
## Benefits
|
|
35
|
-
|
|
36
|
-
| Aspect | Current (Tools) | With Resources |
|
|
37
|
-
|--------|-----------------|----------------|
|
|
38
|
-
| Data access | Tool call required | Direct read |
|
|
39
|
-
| Caching | Manual | MCP native |
|
|
40
|
-
| Subscriptions | Not supported | Supported |
|
|
41
|
-
| Context loading | Via tool results | Direct injection |
|
|
42
|
-
|
|
43
|
-
## Risks
|
|
44
|
-
|
|
45
|
-
- **URI parsing complexity**: Need to handle `ckan://` scheme correctly
|
|
46
|
-
- **Error handling**: Different pattern than tools
|
|
47
|
-
- **Testing**: New test patterns needed for resources
|
|
48
|
-
|
|
49
|
-
## References
|
|
50
|
-
|
|
51
|
-
- [MCP Resources Specification](https://modelcontextprotocol.io/specification/2025-11-25)
|
|
52
|
-
- [Data.gov MCP Server](https://skywork.ai/skypage/en/unlocking-government-data-mcp-server/1980445961155629056) - uses `datagov://` scheme
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
# MCP Resources Capability
|
|
2
|
-
|
|
3
|
-
## ADDED Requirements
|
|
4
|
-
|
|
5
|
-
### Requirement: Dataset Resource Template
|
|
6
|
-
|
|
7
|
-
The system SHALL expose a resource template for accessing CKAN dataset metadata via the URI pattern `ckan://{server}/dataset/{id}`.
|
|
8
|
-
|
|
9
|
-
#### Scenario: Read dataset metadata successfully
|
|
10
|
-
|
|
11
|
-
- **WHEN** client reads `ckan://dati.gov.it/dataset/vaccini-covid`
|
|
12
|
-
- **THEN** server returns JSON with complete dataset metadata including title, description, resources, organization, tags
|
|
13
|
-
|
|
14
|
-
#### Scenario: Dataset not found
|
|
15
|
-
|
|
16
|
-
- **WHEN** client reads `ckan://demo.ckan.org/dataset/nonexistent-id`
|
|
17
|
-
- **THEN** server returns error indicating dataset not found
|
|
18
|
-
|
|
19
|
-
#### Scenario: Server unreachable
|
|
20
|
-
|
|
21
|
-
- **WHEN** client reads `ckan://invalid-server.example/dataset/test`
|
|
22
|
-
- **THEN** server returns error indicating server unreachable
|
|
23
|
-
|
|
24
|
-
### Requirement: Resource Resource Template
|
|
25
|
-
|
|
26
|
-
The system SHALL expose a resource template for accessing CKAN resource metadata via the URI pattern `ckan://{server}/resource/{id}`.
|
|
27
|
-
|
|
28
|
-
#### Scenario: Read resource metadata successfully
|
|
29
|
-
|
|
30
|
-
- **WHEN** client reads `ckan://dati.gov.it/resource/abc-123-def`
|
|
31
|
-
- **THEN** server returns JSON with resource metadata including name, format, URL, size, and download link
|
|
32
|
-
|
|
33
|
-
#### Scenario: Resource not found
|
|
34
|
-
|
|
35
|
-
- **WHEN** client reads `ckan://demo.ckan.org/resource/invalid-id`
|
|
36
|
-
- **THEN** server returns error indicating resource not found
|
|
37
|
-
|
|
38
|
-
### Requirement: Organization Resource Template
|
|
39
|
-
|
|
40
|
-
The system SHALL expose a resource template for accessing CKAN organization metadata via the URI pattern `ckan://{server}/organization/{name}`.
|
|
41
|
-
|
|
42
|
-
#### Scenario: Read organization metadata successfully
|
|
43
|
-
|
|
44
|
-
- **WHEN** client reads `ckan://dati.gov.it/organization/regione-toscana`
|
|
45
|
-
- **THEN** server returns JSON with organization metadata including title, description, and dataset count
|
|
46
|
-
|
|
47
|
-
#### Scenario: Organization not found
|
|
48
|
-
|
|
49
|
-
- **WHEN** client reads `ckan://demo.ckan.org/organization/nonexistent-org`
|
|
50
|
-
- **THEN** server returns error indicating organization not found
|
|
51
|
-
|
|
52
|
-
### Requirement: URI Scheme Parsing
|
|
53
|
-
|
|
54
|
-
The system SHALL parse `ckan://` URIs extracting server hostname and path components.
|
|
55
|
-
|
|
56
|
-
#### Scenario: Parse standard URI
|
|
57
|
-
|
|
58
|
-
- **WHEN** URI is `ckan://dati.gov.it/dataset/test-id`
|
|
59
|
-
- **THEN** server extracts: server=`https://dati.gov.it`, type=`dataset`, id=`test-id`
|
|
60
|
-
|
|
61
|
-
#### Scenario: Parse URI with www prefix
|
|
62
|
-
|
|
63
|
-
- **WHEN** URI is `ckan://www.dati.gov.it/dataset/test-id`
|
|
64
|
-
- **THEN** server extracts: server=`https://www.dati.gov.it`, type=`dataset`, id=`test-id`
|
|
65
|
-
|
|
66
|
-
#### Scenario: Reject malformed URI
|
|
67
|
-
|
|
68
|
-
- **WHEN** URI is `ckan://invalid` (missing path)
|
|
69
|
-
- **THEN** server returns validation error
|
|
70
|
-
|
|
71
|
-
### Requirement: Resource Response Format
|
|
72
|
-
|
|
73
|
-
The system SHALL return resource content as JSON with standard MCP resource response structure.
|
|
74
|
-
|
|
75
|
-
#### Scenario: JSON response structure
|
|
76
|
-
|
|
77
|
-
- **WHEN** client reads any valid resource URI
|
|
78
|
-
- **THEN** response contains `contents` array with `uri`, `mimeType` (application/json), and `text` (JSON string)
|
|
79
|
-
|
|
80
|
-
#### Scenario: Large response truncation
|
|
81
|
-
|
|
82
|
-
- **WHEN** resource content exceeds CHARACTER_LIMIT
|
|
83
|
-
- **THEN** response is truncated to CHARACTER_LIMIT with truncation indicator
|
|
84
|
-
|
|
85
|
-
### Requirement: Resource Discovery
|
|
86
|
-
|
|
87
|
-
The system SHALL list available resource templates when client requests resource list.
|
|
88
|
-
|
|
89
|
-
#### Scenario: List resource templates
|
|
90
|
-
|
|
91
|
-
- **WHEN** client calls `resources/listTemplates`
|
|
92
|
-
- **THEN** server returns list of available URI templates with descriptions
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# Tasks: Add MCP Resource Templates
|
|
2
|
-
|
|
3
|
-
## 1. Setup
|
|
4
|
-
|
|
5
|
-
- [x] 1.1 Create `src/resources/` directory
|
|
6
|
-
- [x] 1.2 Create `src/resources/index.ts` with `registerAllResources()` export
|
|
7
|
-
|
|
8
|
-
## 2. URI Utilities
|
|
9
|
-
|
|
10
|
-
- [x] 2.1 Create URI parsing function for `ckan://` scheme
|
|
11
|
-
- [x] 2.2 Add validation for malformed URIs
|
|
12
|
-
- [x] 2.3 Handle edge cases (www prefix, trailing slashes)
|
|
13
|
-
|
|
14
|
-
## 3. Dataset Resource
|
|
15
|
-
|
|
16
|
-
- [x] 3.1 Create `src/resources/dataset.ts`
|
|
17
|
-
- [x] 3.2 Register template `ckan://{server}/dataset/{id}`
|
|
18
|
-
- [x] 3.3 Implement handler using `makeCkanRequest('package_show')`
|
|
19
|
-
- [x] 3.4 Return JSON response with dataset metadata
|
|
20
|
-
|
|
21
|
-
## 4. Resource Resource
|
|
22
|
-
|
|
23
|
-
- [x] 4.1 Create `src/resources/resource.ts`
|
|
24
|
-
- [x] 4.2 Register template `ckan://{server}/resource/{id}`
|
|
25
|
-
- [x] 4.3 Implement handler using `makeCkanRequest('resource_show')`
|
|
26
|
-
- [x] 4.4 Include download URL in response
|
|
27
|
-
|
|
28
|
-
## 5. Organization Resource
|
|
29
|
-
|
|
30
|
-
- [x] 5.1 Create `src/resources/organization.ts`
|
|
31
|
-
- [x] 5.2 Register template `ckan://{server}/organization/{name}`
|
|
32
|
-
- [x] 5.3 Implement handler using `makeCkanRequest('organization_show')`
|
|
33
|
-
- [x] 5.4 Return JSON response with organization metadata
|
|
34
|
-
|
|
35
|
-
## 6. Integration
|
|
36
|
-
|
|
37
|
-
- [x] 6.1 Import `registerAllResources` in `src/index.ts`
|
|
38
|
-
- [x] 6.2 Call `registerAllResources(server)` after tool registration
|
|
39
|
-
- [x] 6.3 Build and verify no compilation errors
|
|
40
|
-
|
|
41
|
-
## 7. Testing
|
|
42
|
-
|
|
43
|
-
- [x] 7.1 Create `tests/integration/resources.test.ts`
|
|
44
|
-
- [x] 7.2 Add tests for dataset resource template
|
|
45
|
-
- [x] 7.3 Add tests for resource resource template
|
|
46
|
-
- [x] 7.4 Add tests for organization resource template
|
|
47
|
-
- [x] 7.5 Add tests for URI parsing edge cases
|
|
48
|
-
- [x] 7.6 Add tests for error handling (invalid URI, server errors)
|
|
49
|
-
- [x] 7.7 Run full test suite, ensure 100% pass
|
|
50
|
-
|
|
51
|
-
## 8. Documentation
|
|
52
|
-
|
|
53
|
-
- [x] 8.1 Update README.md with resource templates section
|
|
54
|
-
- [x] 8.2 Update CLAUDE.md architecture section
|
|
55
|
-
- [x] 8.3 Add examples to EXAMPLES.md (deferred - basic examples in README)
|
|
56
|
-
- [x] 8.4 Update LOG.md with changes
|