LINDAS MCP Server
The LINDAS MCP Server enables LLMs to discover, explore, and query Swiss federal linked data (RDF cubes) from the LINDAS platform without writing SPARQL.
Discover datasets: List all available data cubes or search by keyword across titles and descriptions.
Inspect cube structure: Retrieve dimensions, measures, datatypes, constraints, and metadata (publisher, license, versions) for any cube.
Explore dimension values: Fetch distinct valid values for any dimension (e.g., cantons, years, categories) with human-readable labels, counts, and ranges.
Query observations: Retrieve data records with optional filters (equality and comparison operators), pagination (
limit/offset), language selection, and automatic IRI-to-label resolution.Count observations: Check how many results a query will return before fetching data.
Geographic lookup: List all 26 Swiss cantons, municipalities, and districts with their LINDAS IRIs, and resolve place names to their corresponding IRIs.
Resolve IRIs: Look up any LINDAS IRI to get its associated label and type.
Guided exploration: Access pre-defined prompt templates to guide common data exploration and canton-comparison workflows.
Browse the catalogue: Explore available cubes via the
lindas:///cubesresource.Flexible deployment: Supports
stdioandhttptransport modes for integration with Claude Desktop, MCP Inspector, opencode, Docker, and more.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@LINDAS MCP ServerCompare population across all cantons for 2023"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
LINDAS MCP Server
A Model Context Protocol server that enables LLMs to query structured data from LINDAS — the Swiss Federal Archives' Linked Data platform at https://ld.admin.ch.
LINDAS stores multi-dimensional statistical data as RDF cubes using the cube.link vocabulary, accessible via a SPARQL endpoint backed by Stardog. This server translates high-level tool calls into SPARQL queries and returns clean, LLM-friendly JSON.
What this enables
Ask an LLM questions about Swiss federal data and let it discover, inspect, and query datasets automatically:
"Show me forest fire danger warnings in the last week"
"Compare population across all cantons for 2023"
"Find datasets about unemployment"
The LLM uses the tools below to discover cubes, inspect their structure, find valid dimension values, and query observations — all without writing SPARQL.
Related MCP server: swiss-statistics-mcp
Prerequisites
Node.js ≥ 20
npm or pnpm
Installation
npm install
npm run buildConfiguration
Environment variables (all optional):
Variable | Default | Description |
|
| SPARQL endpoint URL |
|
| Default language for labels ( |
|
| Transport mode: |
|
| HTTP port (only used when transport is |
|
| HTTP bind address (only used when transport is |
Command-line flags override environment variables:
lindas-mcp [--transport stdio|http] [--port PORT]Usage with Claude Desktop
Add the server to your claude_desktop_config.json:
{
"mcpServers": {
"lindas": {
"command": "node",
"args": ["C:/path/to/lindas-mcp/dist/index.js"],
"env": {
"LINDAS_DEFAULT_LANGUAGE": "de"
}
}
}
}For development with hot reload, use tsx:
{
"mcpServers": {
"lindas": {
"command": "npx",
"args": ["tsx", "C:/path/to/lindas-mcp/src/index.ts"]
}
}
}HTTP Transport (Streamable HTTP)
For use with the MCP Inspector, web-based clients, or remote access, start the server in HTTP mode:
# Using npm scripts
npm run start:http # node dist/index.js --transport http
npm run dev:http # tsx src/index.ts --transport http
# Or directly
node dist/index.js --transport http --port 3000The server exposes the MCP Streamable HTTP endpoint at http://127.0.0.1:3000/mcp.
In HTTP mode, each client session gets its own MCP server instance. The server tracks sessions via the Mcp-Session-Id header.
MCP Inspector
To inspect the server interactively, open the MCP Inspector and connect to:
http://127.0.0.1:3000/mcpOr launch the Inspector with the server:
npx @modelcontextprotocol/inspector node dist/index.js --transport stdioopencode
For HTTP mode in opencode, configure opencode.json:
{
"mcp": {
"lindas": {
"type": "remote",
"url": "http://127.0.0.1:3000/mcp",
"enabled": true
}
}
}LibreChat / Docker
Build the Docker image and add it to your docker-compose.yml:
services:
lindas-mcp:
image: lindas-mcp
container_name: lindas-mcp
environment:
- LINDAS_TRANSPORT=http
- LINDAS_PORT=8000
- LINDAS_DEFAULT_LANGUAGE=de
restart: unless-stopped
# ports: # Only needed for host access
# - "8000:8000"Then in LibreChat's config:
mcpServers:
lindas:
type: streamable-http
url: http://lindas-mcp:8000/mcpMake sure both containers share the same Docker network.
Available Tools
Discovery & Search
Tool | Description | Key Parameters |
| List available data cubes |
|
| Full-text search across cube titles/descriptions |
|
| Get publisher, license, status, temporal coverage, and other metadata for a cube |
|
| List all versions of a cube |
|
| Get dimensions/measures/datatypes of a cube |
|
| Get all dimensions with value counts and available ranges — single-call overview instead of calling |
|
Querying
Tool | Description | Key Parameters |
| Query observations with filters, pagination, and optional label resolution |
|
| Count observations (check size before query) |
|
| Break down observation counts by dimension values (e.g., how many per canton per year) |
|
| Get pagination metadata for a query — total count, hasMore, nextPageOffset |
|
Geography
Tool | Description | Key Parameters |
| List all 26 Swiss cantons with IRIs and names |
|
| List Swiss municipalities with IRIs and names (optionally filtered by canton) |
|
| List Swiss districts with IRIs and names (optionally filtered by canton) |
|
| Resolve a place name to its LINDAS IRI |
|
| Look up a LINDAS IRI to get its label and type |
|
Resources
lindas:///cubes— Catalogue of available data cubes (Markdown)
Prompts
data_exploration— Step-by-step guide for exploring LINDAS datacanton_comparison— Compare a topic across cantons for a given year (args:topic,year)
Typical Workflow
The recommended workflow for an LLM using this server:
search_datasetsorlist_cubes— Find cubes matching the user's topicget_cube_structure— Inspect the cube's dimensions and measuresget_dimension_summary— Get a quick overview of all dimensions with value counts (replaces callingget_dimension_valuesfor each dimension separately)resolve_geography— If the user mentions a place name, resolve it to an IRIresolve_iri— If query results contain opaque IRIs, look up their labelscount_observations— Check how many results the query will returnquery_observations— Retrieve the data (useresolve_labels: trueto get human-readable labels instead of IRIs)
For geographic comparisons, use get_cantons, get_municipalities, or get_districts to list geographic entities with their IRIs.
resolve_labels Feature
When query_observations is called with resolve_labels: true, IRI-valued dimensions are automatically joined to their schema:name labels. Instead of receiving:
{ "canton": { "value": "https://ld.admin.ch/canton/1", "label": "https://ld.admin.ch/canton/1" } }You receive:
{ "canton": { "value": "https://ld.admin.ch/canton/1", "label": "Zürich" } }This makes results immediately understandable without additional lookups.
Development
npm run dev # Start stdio transport with tsx (hot reload)
npm run dev:http # Start HTTP transport with tsx (hot reload)
npm run build # Compile with tsc
npm start # Run compiled stdio server
npm run start:http # Run compiled HTTP server
npm test # Run unit tests (vitest)
npm run test:watch # Watch modeProject Structure
src/
├── index.ts # MCP server entry point (stdio + HTTP)
├── config.ts # Configuration constants
├── sparql/
│ ├── client.ts # SPARQL HTTP client + SparqlError
│ ├── queryBuilder.ts # Pure SPARQL query builder functions
│ └── resultParser.ts # SPARQL JSON → domain object parsers
├── tools/
│ ├── index.ts # Tool registration + dispatch
│ └── *.ts # Individual tool handlers
├── resources/
│ └── catalogue.ts # lindas:///cubes resource
└── prompts/
└── templates.ts # Prompt templates
tests/
├── sparql.test.ts # Query builder unit tests
└── resultParser.test.ts # Parser unit testsNotes
All logging goes to stderr (stdout is reserved for the MCP protocol in stdio mode).
User input interpolated into SPARQL is escaped to prevent injection.
Result limit is capped at 500 to protect LLM context windows.
Labels are fetched via
schema:namewith language filtering; IRI-valued dimensions fall back to the IRI itself if no label is found.The
search_datasetstool usesCONTAINSfilters onschema:nameandschema:description(the StardogtextMatchpredicate is not supported on the public LINDAS endpoint).In HTTP mode, each client session gets its own MCP server instance. Sessions are tracked via the
Mcp-Session-Idheader and cleaned up on disconnect.
License
MIT
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/BFH-JTF/lindas-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server