ckanext-mcp
MCP bridge for CKAN — exposes all API actions from CKAN core and installed extensions as MCP tools. LLMs act as the authenticated user, inheriting all CKAN permissions.
How it works
CKAN installations have ~200 API actions depending on installed extensions. Exposing all of them as flat MCP tools would overwhelm any LLM. Instead, ckanext-mcp builds ~25 synthetic entity tools at startup:
ckan_package— show, list, create, update, delete, patch, searchckan_resource— show, create, update, delete, patch, searchckan_organization— show, list, create, update, delete, patchckan_tag— show, list, create, delete, searchckan_search_tools— discover any of the ~200 actions by keyword, entity, or source- ... and more, derived automatically from installed plugins
Each entity tool bundles CRUD operations. The LLM passes an operation parameter to select the action:
{
"name": "ckan_package",
"arguments": {
"operation": "show",
"id": "my-dataset"
}
}
Zero hardcoding — entity grouping derived from CKAN's naming convention (package_show → entity package), source from IActions plugin registry, read/write from side_effect_free attribute.
Installation
pip install ckanext-mcp
Add mcp to ckan.plugins in your ckan.ini or .env:
ckan.plugins = ... mcp
Configuration
| Option | Default | Description |
|---|---|---|
ckanext.mcp.categories |
(empty) | Comma-separated entity or source filter (e.g. package,resource,harvest) |
The MCP endpoint is always available at /mcp.
Client Setup
Generate a .mcp.json config for your MCP client:
ckan -c ckan.ini mcp init
This creates .mcp.json:
{
"mcpServers": {
"ckan": {
"type": "http",
"url": "https://your-ckan.example.com/mcp",
"headers": {
"Authorization": "Bearer <YOUR_API_KEY>"
}
}
}
}
Replace <YOUR_API_KEY> with your CKAN API key, then point your MCP client (Claude Code, Cursor, etc.) at this file.
Authentication
The bridge piggybacks on CKAN's existing auth:
- API token: pass in
Authorizationheader — CKAN middleware resolves the user before the MCP endpoint runs - Session: browser-based MCP clients use the existing CKAN session
CKAN's action-level auth enforces all permissions. The LLM can only do what the authenticated user can do.
Search & Discovery
The ckan_search_tools tool lets the LLM discover actions beyond the default entity tools:
{
"name": "ckan_search_tools",
"arguments": {"entity": "harvest_source"}
}
Returns full MCP definitions (name, description, inputSchema) for all matching actions — the LLM can then call them through their entity tool.
MCP Protocol
- Spec: 2025-11-25
- Transport: Streamable HTTP (JSON-RPC 2.0 over POST)
- Methods:
initialize,notifications/initialized,tools/list,tools/call - No external MCP dependencies — manual JSON-RPC implementation
Development
git clone https://github.com/Mat-O-Lab/ckanext-mcp.git
cd ckanext-mcp
pip install -e .
pip install -r dev-requirements.txt
Run tests:
pytest --ckan-ini=test.ini ckanext/mcp
License
AGPL-3.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ckanext_mcp-0.1.0.tar.gz.
File metadata
- Download URL: ckanext_mcp-0.1.0.tar.gz
- Upload date:
- Size: 41.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d374175dc98e7bf99b0ee2bc8a893b73461de58ee9cef5fe699c2e20b00ed104
|
|
| MD5 |
6442bcafc7134549b095a672f1d3f31e
|
|
| BLAKE2b-256 |
51670f4d374632de0abcad327a5db4445f4251b224c3145ce22f81c6f5b0c74a
|
Provenance
The following attestation bundles were made for ckanext_mcp-0.1.0.tar.gz:
Publisher:
pypi.yml on ThHanke/ckanext-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ckanext_mcp-0.1.0.tar.gz -
Subject digest:
d374175dc98e7bf99b0ee2bc8a893b73461de58ee9cef5fe699c2e20b00ed104 - Sigstore transparency entry: 2273395726
- Sigstore integration time:
-
Permalink:
ThHanke/ckanext-mcp@6a63ed451ff83dc772966b2aa7211b26e5e53023 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ThHanke
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@6a63ed451ff83dc772966b2aa7211b26e5e53023 -
Trigger Event:
release
-
Statement type:
File details
Details for the file ckanext_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ckanext_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 41.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ce1da71a83086be1660898bee8627b648a83c6345a55c25dffa1897fa453d6d
|
|
| MD5 |
ad0c0a8be918327ec66ab1ce46470436
|
|
| BLAKE2b-256 |
df3e59ef9e30270414b2faf9f11908ab0e780e859d99d19f5c0230b248ad5e89
|
Provenance
The following attestation bundles were made for ckanext_mcp-0.1.0-py3-none-any.whl:
Publisher:
pypi.yml on ThHanke/ckanext-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ckanext_mcp-0.1.0-py3-none-any.whl -
Subject digest:
5ce1da71a83086be1660898bee8627b648a83c6345a55c25dffa1897fa453d6d - Sigstore transparency entry: 2273395798
- Sigstore integration time:
-
Permalink:
ThHanke/ckanext-mcp@6a63ed451ff83dc772966b2aa7211b26e5e53023 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ThHanke
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@6a63ed451ff83dc772966b2aa7211b26e5e53023 -
Trigger Event:
release
-
Statement type: