@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.
Files changed (43) hide show
  1. package/.claude/commands/openspec/apply.md +23 -0
  2. package/.claude/commands/openspec/archive.md +27 -0
  3. package/.claude/commands/openspec/proposal.md +28 -0
  4. package/.claude/settings.local.json +31 -0
  5. package/.gemini/commands/openspec/apply.toml +21 -0
  6. package/.gemini/commands/openspec/archive.toml +25 -0
  7. package/.gemini/commands/openspec/proposal.toml +26 -0
  8. package/.mcp.json +12 -0
  9. package/.opencode/command/openspec-apply.md +24 -0
  10. package/.opencode/command/openspec-archive.md +27 -0
  11. package/.opencode/command/openspec-proposal.md +29 -0
  12. package/AGENTS.md +18 -0
  13. package/CLAUDE.md +320 -0
  14. package/EXAMPLES.md +707 -0
  15. package/LICENSE.txt +21 -0
  16. package/LOG.md +154 -0
  17. package/PRD.md +912 -0
  18. package/README.md +468 -0
  19. package/REFACTORING.md +237 -0
  20. package/dist/index.js +1277 -0
  21. package/openspec/AGENTS.md +456 -0
  22. package/openspec/changes/archive/2026-01-08-add-mcp-resources/design.md +115 -0
  23. package/openspec/changes/archive/2026-01-08-add-mcp-resources/proposal.md +52 -0
  24. package/openspec/changes/archive/2026-01-08-add-mcp-resources/specs/mcp-resources/spec.md +92 -0
  25. package/openspec/changes/archive/2026-01-08-add-mcp-resources/tasks.md +56 -0
  26. package/openspec/changes/archive/2026-01-08-expand-test-coverage-specs/design.md +355 -0
  27. package/openspec/changes/archive/2026-01-08-expand-test-coverage-specs/proposal.md +161 -0
  28. package/openspec/changes/archive/2026-01-08-expand-test-coverage-specs/tasks.md +162 -0
  29. package/openspec/changes/archive/2026-01-08-translate-project-to-english/proposal.md +115 -0
  30. package/openspec/changes/archive/2026-01-08-translate-project-to-english/specs/documentation-language/spec.md +32 -0
  31. package/openspec/changes/archive/2026-01-08-translate-project-to-english/tasks.md +115 -0
  32. package/openspec/changes/archive/add-automated-tests/design.md +324 -0
  33. package/openspec/changes/archive/add-automated-tests/proposal.md +167 -0
  34. package/openspec/changes/archive/add-automated-tests/specs/automated-testing/spec.md +143 -0
  35. package/openspec/changes/archive/add-automated-tests/tasks.md +132 -0
  36. package/openspec/project.md +113 -0
  37. package/openspec/specs/documentation-language/spec.md +32 -0
  38. package/openspec/specs/mcp-resources/spec.md +94 -0
  39. package/package.json +46 -0
  40. package/spunti.md +19 -0
  41. package/tasks/todo.md +124 -0
  42. package/test-urls.js +18 -0
  43. package/tmp/test-org-search.js +55 -0
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: OpenSpec: Apply
3
+ description: Implement an approved OpenSpec change and keep tasks in sync.
4
+ category: OpenSpec
5
+ tags: [openspec, apply]
6
+ ---
7
+ <!-- OPENSPEC:START -->
8
+ **Guardrails**
9
+ - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
10
+ - Keep changes tightly scoped to the requested outcome.
11
+ - Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
12
+
13
+ **Steps**
14
+ Track these steps as TODOs and complete them one by one.
15
+ 1. Read `changes/<id>/proposal.md`, `design.md` (if present), and `tasks.md` to confirm scope and acceptance criteria.
16
+ 2. Work through tasks sequentially, keeping edits minimal and focused on the requested change.
17
+ 3. Confirm completion before updating statuses—make sure every item in `tasks.md` is finished.
18
+ 4. Update the checklist after all work is done so each task is marked `- [x]` and reflects reality.
19
+ 5. Reference `openspec list` or `openspec show <item>` when additional context is required.
20
+
21
+ **Reference**
22
+ - Use `openspec show <id> --json --deltas-only` if you need additional context from the proposal while implementing.
23
+ <!-- OPENSPEC:END -->
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: OpenSpec: Archive
3
+ description: Archive a deployed OpenSpec change and update specs.
4
+ category: OpenSpec
5
+ tags: [openspec, archive]
6
+ ---
7
+ <!-- OPENSPEC:START -->
8
+ **Guardrails**
9
+ - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
10
+ - Keep changes tightly scoped to the requested outcome.
11
+ - Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
12
+
13
+ **Steps**
14
+ 1. Determine the change ID to archive:
15
+ - If this prompt already includes a specific change ID (for example inside a `<ChangeId>` block populated by slash-command arguments), use that value after trimming whitespace.
16
+ - If the conversation references a change loosely (for example by title or summary), run `openspec list` to surface likely IDs, share the relevant candidates, and confirm which one the user intends.
17
+ - Otherwise, review the conversation, run `openspec list`, and ask the user which change to archive; wait for a confirmed change ID before proceeding.
18
+ - If you still cannot identify a single change ID, stop and tell the user you cannot archive anything yet.
19
+ 2. Validate the change ID by running `openspec list` (or `openspec show <id>`) and stop if the change is missing, already archived, or otherwise not ready to archive.
20
+ 3. Run `openspec archive <id> --yes` so the CLI moves the change and applies spec updates without prompts (use `--skip-specs` only for tooling-only work).
21
+ 4. Review the command output to confirm the target specs were updated and the change landed in `changes/archive/`.
22
+ 5. Validate with `openspec validate --strict` and inspect with `openspec show <id>` if anything looks off.
23
+
24
+ **Reference**
25
+ - Use `openspec list` to confirm change IDs before archiving.
26
+ - Inspect refreshed specs with `openspec list --specs` and address any validation issues before handing off.
27
+ <!-- OPENSPEC:END -->
@@ -0,0 +1,28 @@
1
+ ---
2
+ name: OpenSpec: Proposal
3
+ description: Scaffold a new OpenSpec change and validate strictly.
4
+ category: OpenSpec
5
+ tags: [openspec, change]
6
+ ---
7
+ <!-- OPENSPEC:START -->
8
+ **Guardrails**
9
+ - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
10
+ - Keep changes tightly scoped to the requested outcome.
11
+ - Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
12
+ - Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files.
13
+ - Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval.
14
+
15
+ **Steps**
16
+ 1. Review `openspec/project.md`, run `openspec list` and `openspec list --specs`, and inspect related code or docs (e.g., via `rg`/`ls`) to ground the proposal in current behaviour; note any gaps that require clarification.
17
+ 2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, and `design.md` (when needed) under `openspec/changes/<id>/`.
18
+ 3. Map the change into concrete capabilities or requirements, breaking multi-scope efforts into distinct spec deltas with clear relationships and sequencing.
19
+ 4. Capture architectural reasoning in `design.md` when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs.
20
+ 5. Draft spec deltas in `changes/<id>/specs/<capability>/spec.md` (one folder per capability) using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement and cross-reference related capabilities when relevant.
21
+ 6. Draft `tasks.md` as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work.
22
+ 7. Validate with `openspec validate <id> --strict` and resolve every issue before sharing the proposal.
23
+
24
+ **Reference**
25
+ - Use `openspec show <id> --json --deltas-only` or `openspec show <spec> --type spec` to inspect details when validation fails.
26
+ - Search existing requirements with `rg -n "Requirement:|Scenario:" openspec/specs` before writing new ones.
27
+ - Explore the codebase with `rg <keyword>`, `ls`, or direct file reads so proposals align with current implementation realities.
28
+ <!-- OPENSPEC:END -->
@@ -0,0 +1,31 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(node --version:*)",
5
+ "Bash(npm --version:*)",
6
+ "Bash(npm run build:*)",
7
+ "Bash(npx tsc:*)",
8
+ "Bash(npm install:*)",
9
+ "Bash(npx esbuild:*)",
10
+ "Bash(curl:*)",
11
+ "WebSearch",
12
+ "mcp__ckan-mcp__ckan_package_search",
13
+ "mcp__ckan-mcp__ckan_package_show",
14
+ "Bash(cat:*)",
15
+ "mcp__ckan-mcp__ckan_status_show",
16
+ "WebFetch(domain:docs.ckan.org)",
17
+ "mcp__ckan-mcp__ckan_organization_list",
18
+ "mcp__ckan-mcp__ckan_organization_search",
19
+ "Bash(npm test:*)",
20
+ "Bash(wc:*)",
21
+ "Bash(mkdir:*)",
22
+ "WebFetch(domain:skywork.ai)",
23
+ "Bash(grep:*)",
24
+ "Bash(find:*)"
25
+ ]
26
+ },
27
+ "enableAllProjectMcpServers": true,
28
+ "enabledMcpjsonServers": [
29
+ "ckan-mcp"
30
+ ]
31
+ }
@@ -0,0 +1,21 @@
1
+ description = "Implement an approved OpenSpec change and keep tasks in sync."
2
+
3
+ prompt = """
4
+ <!-- OPENSPEC:START -->
5
+ **Guardrails**
6
+ - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
7
+ - Keep changes tightly scoped to the requested outcome.
8
+ - Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
9
+
10
+ **Steps**
11
+ Track these steps as TODOs and complete them one by one.
12
+ 1. Read `changes/<id>/proposal.md`, `design.md` (if present), and `tasks.md` to confirm scope and acceptance criteria.
13
+ 2. Work through tasks sequentially, keeping edits minimal and focused on the requested change.
14
+ 3. Confirm completion before updating statuses—make sure every item in `tasks.md` is finished.
15
+ 4. Update the checklist after all work is done so each task is marked `- [x]` and reflects reality.
16
+ 5. Reference `openspec list` or `openspec show <item>` when additional context is required.
17
+
18
+ **Reference**
19
+ - Use `openspec show <id> --json --deltas-only` if you need additional context from the proposal while implementing.
20
+ <!-- OPENSPEC:END -->
21
+ """
@@ -0,0 +1,25 @@
1
+ description = "Archive a deployed OpenSpec change and update specs."
2
+
3
+ prompt = """
4
+ <!-- OPENSPEC:START -->
5
+ **Guardrails**
6
+ - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
7
+ - Keep changes tightly scoped to the requested outcome.
8
+ - Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
9
+
10
+ **Steps**
11
+ 1. Determine the change ID to archive:
12
+ - If this prompt already includes a specific change ID (for example inside a `<ChangeId>` block populated by slash-command arguments), use that value after trimming whitespace.
13
+ - If the conversation references a change loosely (for example by title or summary), run `openspec list` to surface likely IDs, share the relevant candidates, and confirm which one the user intends.
14
+ - Otherwise, review the conversation, run `openspec list`, and ask the user which change to archive; wait for a confirmed change ID before proceeding.
15
+ - If you still cannot identify a single change ID, stop and tell the user you cannot archive anything yet.
16
+ 2. Validate the change ID by running `openspec list` (or `openspec show <id>`) and stop if the change is missing, already archived, or otherwise not ready to archive.
17
+ 3. Run `openspec archive <id> --yes` so the CLI moves the change and applies spec updates without prompts (use `--skip-specs` only for tooling-only work).
18
+ 4. Review the command output to confirm the target specs were updated and the change landed in `changes/archive/`.
19
+ 5. Validate with `openspec validate --strict` and inspect with `openspec show <id>` if anything looks off.
20
+
21
+ **Reference**
22
+ - Use `openspec list` to confirm change IDs before archiving.
23
+ - Inspect refreshed specs with `openspec list --specs` and address any validation issues before handing off.
24
+ <!-- OPENSPEC:END -->
25
+ """
@@ -0,0 +1,26 @@
1
+ description = "Scaffold a new OpenSpec change and validate strictly."
2
+
3
+ prompt = """
4
+ <!-- OPENSPEC:START -->
5
+ **Guardrails**
6
+ - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
7
+ - Keep changes tightly scoped to the requested outcome.
8
+ - Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
9
+ - Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files.
10
+ - Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval.
11
+
12
+ **Steps**
13
+ 1. Review `openspec/project.md`, run `openspec list` and `openspec list --specs`, and inspect related code or docs (e.g., via `rg`/`ls`) to ground the proposal in current behaviour; note any gaps that require clarification.
14
+ 2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, and `design.md` (when needed) under `openspec/changes/<id>/`.
15
+ 3. Map the change into concrete capabilities or requirements, breaking multi-scope efforts into distinct spec deltas with clear relationships and sequencing.
16
+ 4. Capture architectural reasoning in `design.md` when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs.
17
+ 5. Draft spec deltas in `changes/<id>/specs/<capability>/spec.md` (one folder per capability) using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement and cross-reference related capabilities when relevant.
18
+ 6. Draft `tasks.md` as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work.
19
+ 7. Validate with `openspec validate <id> --strict` and resolve every issue before sharing the proposal.
20
+
21
+ **Reference**
22
+ - Use `openspec show <id> --json --deltas-only` or `openspec show <spec> --type spec` to inspect details when validation fails.
23
+ - Search existing requirements with `rg -n "Requirement:|Scenario:" openspec/specs` before writing new ones.
24
+ - Explore the codebase with `rg <keyword>`, `ls`, or direct file reads so proposals align with current implementation realities.
25
+ <!-- OPENSPEC:END -->
26
+ """
package/.mcp.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "mcpServers": {
3
+ "ckan-mcp": {
4
+ "type": "stdio",
5
+ "command": "node",
6
+ "args": [
7
+ "/home/aborruso/git/idee/ckan-mcp-server/dist/index.js"
8
+ ],
9
+ "env": {}
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,24 @@
1
+ ---
2
+ description: Implement an approved OpenSpec change and keep tasks in sync.
3
+ ---
4
+ The user has requested to implement the following change proposal. Find the change proposal and follow the instructions below. If you're not sure or if ambiguous, ask for clarification from the user.
5
+ <UserRequest>
6
+ $ARGUMENTS
7
+ </UserRequest>
8
+ <!-- OPENSPEC:START -->
9
+ **Guardrails**
10
+ - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
11
+ - Keep changes tightly scoped to the requested outcome.
12
+ - Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
13
+
14
+ **Steps**
15
+ Track these steps as TODOs and complete them one by one.
16
+ 1. Read `changes/<id>/proposal.md`, `design.md` (if present), and `tasks.md` to confirm scope and acceptance criteria.
17
+ 2. Work through tasks sequentially, keeping edits minimal and focused on the requested change.
18
+ 3. Confirm completion before updating statuses—make sure every item in `tasks.md` is finished.
19
+ 4. Update the checklist after all work is done so each task is marked `- [x]` and reflects reality.
20
+ 5. Reference `openspec list` or `openspec show <item>` when additional context is required.
21
+
22
+ **Reference**
23
+ - Use `openspec show <id> --json --deltas-only` if you need additional context from the proposal while implementing.
24
+ <!-- OPENSPEC:END -->
@@ -0,0 +1,27 @@
1
+ ---
2
+ description: Archive a deployed OpenSpec change and update specs.
3
+ ---
4
+ <ChangeId>
5
+ $ARGUMENTS
6
+ </ChangeId>
7
+ <!-- OPENSPEC:START -->
8
+ **Guardrails**
9
+ - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
10
+ - Keep changes tightly scoped to the requested outcome.
11
+ - Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
12
+
13
+ **Steps**
14
+ 1. Determine the change ID to archive:
15
+ - If this prompt already includes a specific change ID (for example inside a `<ChangeId>` block populated by slash-command arguments), use that value after trimming whitespace.
16
+ - If the conversation references a change loosely (for example by title or summary), run `openspec list` to surface likely IDs, share the relevant candidates, and confirm which one the user intends.
17
+ - Otherwise, review the conversation, run `openspec list`, and ask the user which change to archive; wait for a confirmed change ID before proceeding.
18
+ - If you still cannot identify a single change ID, stop and tell the user you cannot archive anything yet.
19
+ 2. Validate the change ID by running `openspec list` (or `openspec show <id>`) and stop if the change is missing, already archived, or otherwise not ready to archive.
20
+ 3. Run `openspec archive <id> --yes` so the CLI moves the change and applies spec updates without prompts (use `--skip-specs` only for tooling-only work).
21
+ 4. Review the command output to confirm the target specs were updated and the change landed in `changes/archive/`.
22
+ 5. Validate with `openspec validate --strict` and inspect with `openspec show <id>` if anything looks off.
23
+
24
+ **Reference**
25
+ - Use `openspec list` to confirm change IDs before archiving.
26
+ - Inspect refreshed specs with `openspec list --specs` and address any validation issues before handing off.
27
+ <!-- OPENSPEC:END -->
@@ -0,0 +1,29 @@
1
+ ---
2
+ description: Scaffold a new OpenSpec change and validate strictly.
3
+ ---
4
+ The user has requested the following change proposal. Use the openspec instructions to create their change proposal.
5
+ <UserRequest>
6
+ $ARGUMENTS
7
+ </UserRequest>
8
+ <!-- OPENSPEC:START -->
9
+ **Guardrails**
10
+ - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
11
+ - Keep changes tightly scoped to the requested outcome.
12
+ - Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
13
+ - Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files.
14
+ - Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval.
15
+
16
+ **Steps**
17
+ 1. Review `openspec/project.md`, run `openspec list` and `openspec list --specs`, and inspect related code or docs (e.g., via `rg`/`ls`) to ground the proposal in current behaviour; note any gaps that require clarification.
18
+ 2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, and `design.md` (when needed) under `openspec/changes/<id>/`.
19
+ 3. Map the change into concrete capabilities or requirements, breaking multi-scope efforts into distinct spec deltas with clear relationships and sequencing.
20
+ 4. Capture architectural reasoning in `design.md` when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs.
21
+ 5. Draft spec deltas in `changes/<id>/specs/<capability>/spec.md` (one folder per capability) using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement and cross-reference related capabilities when relevant.
22
+ 6. Draft `tasks.md` as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work.
23
+ 7. Validate with `openspec validate <id> --strict` and resolve every issue before sharing the proposal.
24
+
25
+ **Reference**
26
+ - Use `openspec show <id> --json --deltas-only` or `openspec show <spec> --type spec` to inspect details when validation fails.
27
+ - Search existing requirements with `rg -n "Requirement:|Scenario:" openspec/specs` before writing new ones.
28
+ - Explore the codebase with `rg <keyword>`, `ls`, or direct file reads so proposals align with current implementation realities.
29
+ <!-- OPENSPEC:END -->
package/AGENTS.md ADDED
@@ -0,0 +1,18 @@
1
+ <!-- OPENSPEC:START -->
2
+ # OpenSpec Instructions
3
+
4
+ These instructions are for AI assistants working in this project.
5
+
6
+ Always open `@/openspec/AGENTS.md` when the request:
7
+ - Mentions planning or proposals (words like proposal, spec, change, plan)
8
+ - Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
9
+ - Sounds ambiguous and you need the authoritative spec before coding
10
+
11
+ Use `@/openspec/AGENTS.md` to learn:
12
+ - How to create and apply change proposals
13
+ - Spec format and conventions
14
+ - Project structure and guidelines
15
+
16
+ Keep this managed block so 'openspec update' can refresh the instructions.
17
+
18
+ <!-- OPENSPEC:END -->
package/CLAUDE.md ADDED
@@ -0,0 +1,320 @@
1
+ <!-- OPENSPEC:START -->
2
+ # OpenSpec Instructions
3
+
4
+ These instructions are for AI assistants working in this project.
5
+
6
+ Always open `@/openspec/AGENTS.md` when the request:
7
+ - Mentions planning or proposals (words like proposal, spec, change, plan)
8
+ - Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
9
+ - Sounds ambiguous and you need the authoritative spec before coding
10
+
11
+ Use `@/openspec/AGENTS.md` to learn:
12
+ - How to create and apply change proposals
13
+ - Spec format and conventions
14
+ - Project structure and guidelines
15
+
16
+ Keep this managed block so 'openspec update' can refresh the instructions.
17
+
18
+ <!-- OPENSPEC:END -->
19
+
20
+ # CLAUDE.md
21
+
22
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
23
+
24
+ **Important**: This project uses **English** as its primary language. All documentation, code comments, and commit messages should be in English.
25
+
26
+ ## Project Overview
27
+
28
+ CKAN MCP Server - MCP (Model Context Protocol) server for interacting with CKAN-based open data portals (dati.gov.it, data.gov, demo.ckan.org, etc.).
29
+
30
+ The server exposes MCP tools for:
31
+ - Advanced dataset search with Solr syntax
32
+ - DataStore queries for tabular data analysis
33
+ - Organization and group exploration
34
+ - Complete metadata access
35
+
36
+ ## Build and Development
37
+
38
+ ### Main Commands
39
+
40
+ ```bash
41
+ # Build project (uses esbuild - fast and lightweight)
42
+ npm run build
43
+
44
+ # Run test suite (79 tests - unit + integration)
45
+ npm test
46
+
47
+ # Watch mode for tests during development
48
+ npm run test:watch
49
+
50
+ # Test coverage report
51
+ npm run test:coverage
52
+
53
+ # Start server in stdio mode (default for local integration)
54
+ npm start
55
+
56
+ # Start server in HTTP mode (for remote access)
57
+ TRANSPORT=http PORT=3000 npm start
58
+
59
+ # Watch mode for development
60
+ npm run watch
61
+
62
+ # Build + run
63
+ npm run dev
64
+ ```
65
+
66
+ ### Build System
67
+
68
+ The project uses **esbuild** for compilation and **vitest** for testing:
69
+
70
+ - **Build**: Ultra-fast builds (milliseconds instead of minutes)
71
+ - **Tests**: 101 tests (unit + integration) with 100% success rate
72
+ - **Coverage**: Available via vitest with v8 coverage engine
73
+
74
+ 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.
75
+
76
+ The esbuild build bundles all internal modules but keeps external dependencies (`@modelcontextprotocol/sdk`, `axios`, `express`, `zod`) as external, so they must be present in `node_modules`.
77
+
78
+ ### Testing
79
+
80
+ The project has a comprehensive test suite using **Vitest**:
81
+
82
+ ```
83
+ tests/
84
+ ├── unit/
85
+ │ ├── formatting.test.ts # Utility functions (19 tests)
86
+ │ ├── http.test.ts # HTTP client (6 tests)
87
+ │ └── uri.test.ts # URI parsing (11 tests)
88
+ ├── integration/
89
+ │ ├── package.test.ts # Package tools (29 tests)
90
+ │ ├── organization.test.ts # Organization tools (6 tests)
91
+ │ ├── datastore.test.ts # DataStore tools (17 tests)
92
+ │ ├── resources.test.ts # MCP Resources (11 tests)
93
+ │ └── status.test.ts # Status tools (2 tests)
94
+ └── fixtures/
95
+ ├── responses/ # Success response mocks
96
+ └── errors/ # Error scenario mocks
97
+ ```
98
+
99
+ **Test Coverage**: 101 tests total (36 unit + 65 integration)
100
+
101
+ When making changes:
102
+ 1. Run tests before committing: `npm test`
103
+ 2. Ensure all tests pass
104
+ 3. Add tests for new features or bug fixes
105
+ 4. Follow existing test patterns in `tests/` directory
106
+
107
+ ## Architecture
108
+
109
+ ### Code Structure
110
+
111
+ The server is implemented with a modular structure to improve maintainability and testability:
112
+
113
+ ```
114
+ src/
115
+ ├── index.ts # Entry point (42 lines)
116
+ ├── server.ts # MCP server setup (12 lines)
117
+ ├── types.ts # Types & schemas (16 lines)
118
+ ├── utils/
119
+ │ ├── http.ts # CKAN API client (51 lines)
120
+ │ └── formatting.ts # Output formatting (37 lines)
121
+ ├── tools/
122
+ │ ├── package.ts # Package tools (350 lines)
123
+ │ ├── organization.ts # Organization tools (341 lines)
124
+ │ ├── datastore.ts # DataStore tools (146 lines)
125
+ │ └── status.ts # Status tools (66 lines)
126
+ ├── resources/ # MCP Resource Templates
127
+ │ ├── index.ts # Resource registration (19 lines)
128
+ │ ├── uri.ts # URI parsing utilities (50 lines)
129
+ │ ├── dataset.ts # Dataset resource (56 lines)
130
+ │ ├── resource.ts # Resource resource (56 lines)
131
+ │ └── organization.ts # Organization resource (58 lines)
132
+ └── transport/
133
+ ├── stdio.ts # Stdio transport (12 lines)
134
+ └── http.ts # HTTP transport (27 lines)
135
+ ```
136
+
137
+ **Total**: ~1350 lines (including new resources module)
138
+
139
+ The server (`src/index.ts`):
140
+
141
+ 1. **Entry Point** (`index.ts`)
142
+ - Imports and registers all tools
143
+ - Chooses transport (stdio/http) from environment variable
144
+ - Handles startup and error handling
145
+
146
+ 2. **Registered Tools** (in separate modules)
147
+ - `tools/package.ts`: `ckan_package_search`, `ckan_package_show`
148
+ - `tools/organization.ts`: `ckan_organization_list`, `ckan_organization_show`, `ckan_organization_search`
149
+ - `tools/datastore.ts`: `ckan_datastore_search`
150
+ - `tools/status.ts`: `ckan_status_show`
151
+
152
+ 3. **MCP Resource Templates** (`resources/`)
153
+ - `ckan://{server}/dataset/{id}` - Dataset metadata
154
+ - `ckan://{server}/resource/{id}` - Resource metadata
155
+ - `ckan://{server}/organization/{name}` - Organization metadata
156
+
157
+ 4. **Utility Functions** (`utils/`)
158
+ - `http.ts`: `makeCkanRequest<T>()` - HTTP client for CKAN API v3
159
+ - `formatting.ts`: `truncateText()`, `formatDate()`, `formatBytes()`
160
+
161
+ 5. **Type Definitions** (`types.ts`)
162
+ - `ResponseFormat` enum (MARKDOWN, JSON)
163
+ - `ResponseFormatSchema` Zod validator
164
+ - `CHARACTER_LIMIT` constant
165
+
166
+ 5. **Transport Layer** (`transport/`)
167
+ - `stdio.ts`: Standard input/output (Claude Desktop)
168
+ - `http.ts`: HTTP server (remote access)
169
+
170
+ 6. **Validation Schema**
171
+ - Uses Zod to validate all tool inputs
172
+ - Each tool has a strict schema that rejects extra parameters
173
+
174
+ 7. **Output Formatting**
175
+ - All tools support two formats: `markdown` (default) and `json`
176
+ - Markdown format optimized for human readability
177
+ - JSON format for programmatic processing
178
+
179
+ ### Transport Modes
180
+
181
+ The server automatically selects the transport mode based on the `TRANSPORT` environment variable:
182
+
183
+ - **stdio** (default): for integration with Claude Desktop and other local MCP clients
184
+ - **http**: exposes POST `/mcp` endpoint on configurable port (default 3000)
185
+
186
+ ### CKAN API Integration
187
+
188
+ The server uses CKAN API v3 available on any CKAN portal. All requests:
189
+
190
+ - Use `axios` with 30 second timeout
191
+ - Send User-Agent `CKAN-MCP-Server/1.0`
192
+ - Handle HTTP errors, timeouts, and server not found
193
+ - Normalize server URL (removing trailing slash)
194
+ - Validate that `response.success === true`
195
+
196
+ ### Solr Queries
197
+
198
+ CKAN uses Apache Solr for search. The `ckan_package_search` tool supports:
199
+
200
+ - **q** (query): complete Solr syntax (field:value, AND/OR/NOT, wildcard, range)
201
+ - **fq** (filter query): additional filters without affecting score
202
+ - **facet_field**: aggregations for statistical analysis
203
+ - **sort**: result ordering
204
+ - **start/rows**: pagination
205
+
206
+ Common query examples are documented in `EXAMPLES.md`.
207
+
208
+ ## TypeScript Configuration
209
+
210
+ The project uses ES2022 as target and module system.
211
+
212
+ **Note**: `tsconfig.json` is present mainly for editor support (IDE, LSP). The actual compilation uses esbuild which ignores most TypeScript options to maximize speed.
213
+
214
+ TypeScript configuration (for IDE):
215
+ - Output in `dist/` directory
216
+ - Strict mode enabled
217
+ - Strict type checking with noUnusedLocals, noUnusedParameters, noImplicitReturns
218
+ - Skip lib check to reduce overhead
219
+ - Declaration and source map disabled
220
+
221
+ ## Dependencies
222
+
223
+ **Runtime**:
224
+ - `@modelcontextprotocol/sdk` - Official MCP SDK
225
+ - `axios` - HTTP client for CKAN API
226
+ - `zod` - Schema validation
227
+ - `express` - HTTP server (only for http mode)
228
+
229
+ **Dev**:
230
+ - `esbuild` - Build tool (bundler and compiler)
231
+ - `typescript` - Only for type checking and editor support
232
+ - `@types/node`, `@types/express` - Type definitions
233
+
234
+ ## Supported CKAN Portals
235
+
236
+ The server can connect to any CKAN instance. Some main portals:
237
+
238
+ - 🇮🇹 https://dati.gov.it (Italy)
239
+ - 🇺🇸 https://catalog.data.gov (United States)
240
+ - 🇨🇦 https://open.canada.ca/data (Canada)
241
+ - 🇬🇧 https://data.gov.uk (United Kingdom)
242
+ - 🇪🇺 https://data.europa.eu (European Union)
243
+ - 🌍 https://demo.ckan.org (Official CKAN Demo)
244
+
245
+ Each portal may have different configurations for:
246
+ - DataStore availability
247
+ - Custom dataset fields
248
+ - Available organizations and tags
249
+ - Supported resource formats
250
+
251
+
252
+ The project uses **Vitest** for automated testing:
253
+
254
+ ```bash
255
+ # Run all tests
256
+ npm test
257
+
258
+ # Run tests in watch mode
259
+ npm run test:watch
260
+
261
+ # Run tests with coverage report
262
+ npm run test:coverage
263
+ ```
264
+
265
+ Test coverage target is 80%. Current test suite includes:
266
+ - Unit tests for utility functions (formatting, HTTP)
267
+ - Integration tests for MCP tools with mocked CKAN API responses
268
+ - Mock fixtures for CKAN API success and error scenarios
269
+
270
+ See `tests/README.md` for detailed testing guidelines and fixture structure.
271
+
272
+ ### Manual Testing
273
+
274
+ For manual testing:
275
+
276
+ ```bash
277
+ # Build project
278
+ npm run build
279
+
280
+ # Test stdio mode
281
+ npm start
282
+ # (Server will wait for MCP commands on stdin)
283
+
284
+ # Test HTTP mode in a terminal
285
+ TRANSPORT=http PORT=3000 npm start
286
+
287
+ # In another terminal, test with curl
288
+ curl -X POST http://localhost:3000/mcp \
289
+ -H "Content-Type: application/json" \
290
+ -d {"jsonrpc":"2.0","method":"tools/list","id":1}
291
+ ```
292
+
293
+ To test with Claude Desktop, add MCP configuration to config file.
294
+ To test with Claude Desktop, add the MCP configuration to the config file.
295
+
296
+ ## Note di Sviluppo
297
+
298
+ ### Refactoring 2026-01-08
299
+ Il codebase è stato refactorizzato da un singolo file di 1021 righe a 11 moduli. Vedi `REFACTORING.md` per dettagli.
300
+
301
+ **Vantaggi**:
302
+ - File più piccoli (max 350 righe)
303
+ - Modifiche localizzate e sicure
304
+ - Testing isolato possibile
305
+ - Manutenzione semplificata
306
+ - Zero breaking changes
307
+
308
+ ### To Do
309
+ - Non ci sono test automatizzati - considerare di aggiungerli per tool critici
310
+ - Il limite di 50000 caratteri per l'output è hardcoded in `types.ts` - potrebbe essere configurabile
311
+ - Formato date usa locale 'it-IT' in `utils/formatting.ts` - potrebbe essere parametrizzato
312
+ - Il server supporta solo lettura (tutti i tool sono read-only, non modificano dati su CKAN)
313
+ - Non c'è caching - ogni richiesta fa una chiamata HTTP fresca alle API CKAN
314
+ - Non c'è autenticazione - usa solo endpoint pubblici CKAN
315
+
316
+ ### Adding New Tools
317
+ 1. Crea nuovo file in `src/tools/`
318
+ 2. Esporta `registerXxxTools(server: McpServer)`
319
+ 3. Importa e chiama in `src/index.ts`
320
+ 4. Build e test