
Gives Claude direct access to DanNet, the Danish WordNet, through SPARQL queries against an RDF knowledge graph. You get lexical relationships, word senses, synsets, and semantic connections for Danish vocabulary. Built on Apache Jena with Ontolex-lemon standards and Global Wordnet Association relations. The server exposes the same data browsable at wordnet.dk but queryable programmatically. Reach for this when building Danish language tools, doing lexical analysis, or needing structured semantic data about Danish words and their relationships. The underlying dataset also includes sentiment data and links to English WordNet through companion datasets.
DanNet is a WordNet for the Danish language. DanNet uses RDF as its native representation at both the database level, in the application space, and as its primary serialisation format.
DanNet is available in multiple formats to maximise compatibility:
| Format | Description |
|---|---|
| RDF (Turtle) | Native representation. Load into any RDF graph database (such as Apache Jena) and query with SPARQL. |
| CSV | Published with column metadata as CSVW. |
| WN-LMF | XML format compatible with Python libraries like wn. |
| DMLex | OASIS DMLex 1.0 representation as both XML and JSON, in a Danish and an English variant. The DMLex browser shows it as a dictionary. |
import wn
wn.add("dannet-wn-lmf.xml.gz")
for synset in wn.synsets('kage'):
print((synset.lexfile() or "?") + ": " + (synset.definition() or "?"))
While every format includes all synsets/senses/words, the CSV, WN-LMF and DMLex variants do not include every data point:
For the complete dataset, use the RDF format or browse at wordnet.dk.
Several companion datasets expand the RDF graph with additional data:
| Dataset | Description |
|---|---|
| COR | Links DanNet resources to IDs from the COR project. |
| DDS | Adds sentiment data to DanNet resources. |
| OEWN extension | Provides DanNet-style labels for the Open English WordNet to facilitate browsing connections between the two datasets. |
Additional data is implicitly inferred from the base dataset, companion datasets, and ontological metadata. These inferences can be browsed at wordnet.dk. Releases containing fully inferred graphs are specifically marked as such.
DanNet is based on the Ontolex-lemon standard combined with relations defined by the Global Wordnet Association as used in the official GWA RDF standard.
| Ontolex-lemon class | Represents |
|---|---|
ontolex:LexicalConcept | Synsets |
ontolex:LexicalSense | Word senses |
ontolex:LexicalEntry | Words |
ontolex:Form | Forms |

| Prefix | URI | Purpose |
|---|---|---|
dn | https://wordnet.dk/dannet/data/ | Dataset instances |
dnc | https://wordnet.dk/dannet/concepts/ | Ontological type members |
dns | https://wordnet.dk/dannet/schema/ | Schema definitions |
dnf | https://wordnet.dk/dannet/function/ | Custom SPARQL functions (dnf:path, dnf:lch, dnf:wup synset similarity) |
All DanNet URIs resolve to HTTP resources. Accessing one of these URIs via a GET request returns the data for that resource.
DanNet has proprietary relations defined in the DanNet schema in an Ontolex-compatible way. There is also a schema for EuroWordNet concepts. Both schemas follow the RDF conventions listed by Philippe Martin.
DanNet can be connected to AI tools like Claude via MCP (Model Context Protocol).
https://wordnet.dk/mcpio.github.kuhumcst/dannetTo connect in e.g. Claude Desktop: go to Settings > Connectors > Browse Connectors, click "add a custom one", enter a name (e.g., "DanNet") and the MCP server URL.

Once connected, you can query DanNet's semantic relations directly through Claude.
The database backend is Apache Jena, a mature RDF triplestore with OWL inference support. When represented in Jena, DanNet's relations form a queryable knowledge graph. DanNet is developed in Clojure, using libraries like Aristotle to interact with Jena.
See rationale.md for more on the design decisions.
The production deployment at wordnet.dk consists of three services managed via Docker Compose:
DanNet can be queried in various ways from Clojure (see queries.md). Apache Jena transactions are built-in and enable persistence via the TDB 2 layer.
The frontend is written in ClojureScript using Rum, served by Pedestal. The app works both as a single-page application (with JavaScript) and as a regular HTML website (without). Content negotiation serves different representations (HTML, RDF, Transit+JSON) based on the request.
See doc/web.md for details.
New releases are bootstrapped from the preceding release. The process (in dk.cst.dannet.db.bootstrap):
to differs from from)Bootstrap data lives under
./bootstraprelative to the execution directory: the DanNet release assets in./bootstrap/from/<version>/(named after the release being bootstrapped from, so several can coexist) and the shared English datasets in./bootstrap/other/english/. Missing files are downloaded automatically, so manual placement is only needed when working offline.
DanNet requires Java and Clojure's official CLI tools. Dependencies are specified in deps.edn.
(restart) in dk.cst.dannet.web.service — available at localhost:3456npx shadow-cljs watch app
Using Docker (requires Docker daemon running):
# From the docker/ directory
docker compose up --build
Or manually:
shadow-cljs --aliases :frontend release app
clojure -T:build org.corfield.build/uber :lib dk.cst/dannet :main dk.cst.dannet.web.service :uber-file "\"dannet.jar\""
java -jar -Xmx4g dannet.jar
The system uses ~1.5 GB when idle and ~3 GB when rebuilding the database. A server should have at least 4 GB of available RAM.
The dn: dataset is validated against SHACL shapes located in resources/schemas/internal/shapes/ (see dk.cst.dannet.db.shapes). This happens in several ways:
dn: dataset are gated: a baseline regression aborts the export, andclojure -X:validate:test, which is also executed by the GitHub Actions workflow in .github/workflows/test.yml.python3 -m venv examples/venv
source examples/venv/bin/activate
python3 -m pip install wn
python -m wn validate --output-file examples/wn-lmf-validation.json export/wn-lmf/dannet-wn-lmf.xml
The validator in dk.cst.dannet.db.export.dmlex-validate checks both serializations of a variant against the official DMLex schemas. It needs the :validate alias:
clojure -M:validate -e "((requiring-resolve 'dk.cst.dannet.db.export.dmlex-validate/validate-dmlex!) \"export/dmlex/\" \"da\")"
The production server at wordnet.dk runs as a systemd service delegating to Docker.
cp system/dannet.service /etc/systemd/system/dannet.service
systemctl enable dannet
systemctl start dannet
To update the web service software without changing the database:
# From the docker/ directory
docker compose up -d dannet --build
When releasing a new version of the database:
Set to in dk.cst.dannet.release to the
new version, leaving from on the release being bootstrapped from. The
release-specific changes in make-release-changes! only run once the two
differ.
Build the database via REPL in dk.cst.dannet.web.service:
(restart)
Generate the export artifacts, each in its own namespace:
(dk.cst.dannet.db.export.rdf/export-rdf! @dk.cst.dannet.web.resources/db)
(dk.cst.dannet.db.export.csv/export-csv! @dk.cst.dannet.web.resources/db)
(dk.cst.dannet.db.export.wn-lmf/export-wn-lmf! "export/wn-lmf/")
(dk.cst.dannet.db.export.dmlex/export-dmlex-variants! "export/dmlex/" @dk.cst.dannet.web.resources/db)
;; ~6 minutes
(dk.cst.dannet.db.query/save-synset-indegrees!
(:graph @dk.cst.dannet.web.resources/db))
This writes export/rdf/ (dannet.zip, cor.zip, cor-sem.zip,
framenet.zip, dds.zip, oewn-extension.zip), export/csv/dannet-csv.zip,
export/wn-lmf/dannet-wn-lmf.xml.gz, export/dmlex/ (dannet-dmlex-da.zip,
dannet-dmlex-en.zip) and export/synset-indegree.edn. These ship to
production (step 7) and become the GitHub release assets that the next
cycle bootstraps from (step 4).
Publish a GitHub release tagged v<version> and attach the bootstrap assets
listed by bootstrap-files in dk.cst.dannet.db.bootstrap.downloads:
dannet.zip, cor.zip, cor-sem.zip, dds.zip, oewn-extension.zip and
synset-indegree.edn. The next cycle fetches these from GitHub.
Compact the database, then zip it on the dev machine, ready for transfer:
(dk.cst.dannet.db/compact! (:dataset @dk.cst.dannet.web.instance/db))
TDB2 only reclaims the space left by in-place updates when compacted, and
writes a new Data-000N generation, so restart the service afterwards.
Before transferring, check that the database size divided by the triple
count is in the hundreds of bytes, not the thousands.
Stop the service on production:
docker compose stop dannet
Transfer database and export files via SFTP, then:
unzip -o tdb2.zip -d /dannet/db/
mv cor.zip cor-sem.zip framenet.zip dannet.zip dds.zip oewn-extension.zip /dannet/export/rdf/
mv dannet-csv.zip /dannet/export/csv/
mv dannet-wn-lmf.xml.gz /dannet/export/wn-lmf/
mv dannet-dmlex-da.zip dannet-dmlex-en.zip /dannet/export/dmlex/
Ship the export/synset-indegree.edn generated in step 3. Production runs
with --no-bootstrap and so never downloads it, but it is read at query time
to rank search results and entity relations, and it should describe the
database actually being shipped. Either location works, the first taking
precedence (see indegrees-files in
dk.cst.dannet.db.query):
mv synset-indegree.edn /dannet/db/ # legacy location
mv synset-indegree.edn /dannet/bootstrap/from/2026-08-03/ # alongside the bootstrap inputs
If neither exists the service still starts and search still works, but results
come back unranked and a :dannet.query/indegrees-unavailable error is logged.
Restart:
docker compose up -d dannet --build
Bump from to the new version and delete to, which then defaults to from
again. Clear out the release-specific block in make-release-changes!: its
changes have now shipped. This readies the next cycle.