Lightdash MCP Server
# Lightdash MCP Server
[](https://opensource.org/licenses/MIT)
[](https://www.python.org/downloads/)
[](https://modelcontextprotocol.io/)
[](https://pypi.org/project/lightdash-mcp/)
[](https://github.com/poddubnyoleg/lightdash_mcp/stargazers)
> Connect Claude, Cursor, and other AI assistants to your Lightdash analytics using the Model Context Protocol (MCP).
A Model Context Protocol (MCP) server for interacting with [Lightdash](https://www.lightdash.com/), enabling LLMs to discover data, create charts, and manage dashboards programmatically.
## Features
This MCP server provides a comprehensive set of tools for the full data analytics workflow:
* **Discovery**: Explore data catalogs, find tables/explores, and understand schemas
* **Querying**: Execute queries with full filter, metric, and aggregation support
* **Chart Management**: Create, read, update, and delete charts with complex visualizations
* **Dashboard Management**: Build and manage dashboards with tiles, filters, and layouts
* **Resource Organization**: Create and manage spaces for content organization
## Installation
### Prerequisites
* Python 3.10+
* A Lightdash instance (Cloud or self-hosted)
* Lightdash Personal Access Token (obtain from your Lightdash profile settings)
### Quick Start with pip (Recommended)
```bash
pip install lightdash-mcp
```
### Quick Start with uvx
```bash
uvx lightdash-mcp
```
### Quick Start with pipx
```bash
pipx run lightdash-mcp
```
### Install from Source
```bash
git clone https://github.com/poddubnyoleg/lightdash_mcp.git
cd lightdash_mcp
pip install .
```
### Google Cloud IAP Support
If your Lightdash instance is behind [Google Cloud Identity-Aware Proxy](https://cloud.google.com/iap) (e.g. Cloud Run with `--iap`), install with the `iap` extra:
```bash
pip install lightdash-mcp[iap]
# or from source
pip install .[iap]
```
Set `IAP_ENABLED=true`. The server will sign a JWT (audience `{LIGHTDASH_URL}/*`) via the IAM Credentials API and attach it as `Proxy-Authorization: Bearer <jwt>` on every request. The `Authorization: ApiKey` header is preserved for Lightdash.
Both service account credentials and user credentials (Application Default Credentials / ADC) are supported:
**Service account credentials** (default in Cloud Run, GCE, etc.):
- The runtime service account needs `roles/iam.serviceAccountTokenCreator` on itself
- The runtime service account needs `roles/iap.httpsResourceAccessor` on the Cloud Run service
**User credentials (ADC)** (e.g. `gcloud auth application-default login`):
- Set `IAP_SA` to the service account email to impersonate for signing the JWT
- The user needs `roles/iam.serviceAccountTokenCreator` on the target service account
- The target service account needs `roles/iap.httpsResourceAccessor` on the Cloud Run service
## Configuration
### Environment Variables
The server requires the following environment variables:
| Variable | Required | Description | Example |
| :--- | :---: | :--- | :--- |
| `LIGHTDASH_TOKEN` | ✅ | Your Lightdash Personal Access Token | `ldt_abc123...` |
| `LIGHTDASH_URL` | ✅ | Base URL of your Lightdash Instance | `https://app.lightdash.cloud` |
| `CF_ACCESS_CLIENT_ID` | ❌ | Cloudflare Access Client ID (if behind CF Access) | - |
| `CF_ACCESS_CLIENT_SECRET` | ❌ | Cloudflare Access Client Secret (if behind CF Access) | - |
| `LIGHTDASH_PROJECT_UUID` | ❌ | Default project UUID (falls back to first available project) | `3fc2835f-...` |
| `IAP_ENABLED` | ❌ | Enable Google Cloud IAP authentication (`true`/`1`) | `true` |
| `IAP_SA` | ❌ | Service account email for IAP when using user credentials (ADC) | `sa@project.iam.gserviceaccount.com` |
### Getting Your Lightdash Token
1. Log into your Lightdash instance
2. Go to **Settings** → **Personal Access Tokens**
3. Click **Generate new token**
4. Copy the token (starts with `ldt_`)
### Usage with Claude Desktop
Add the following to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"lightdash": {
"command": "uvx",
"args": ["lightdash-mcp"],
"env": {
"LIGHTDASH_TOKEN": "ldt_your_token_here",
"LIGHTDASH_URL": "https://app.lightdash.cloud",
"LIGHTDASH_PROJECT_UUID": "your-project-uuid"
}
}
}
}
```
### Usage with Claude Code (CLI)
Create or edit `.mcp.json` in your project root:
```json
{
"mcpServers": {
"lightdash": {
"type": "stdio",
"command": "lightdash-mcp",
"env": {
"LIGHTDASH_URL": "https://your-lightdash-instance.com",
"LIGHTDASH_TOKEN": "ldt_your_token_here",
"LIGHTDASH_PROJECT_UUID": "your-project-uuid"
}
}
}
}
```
Restart Claude Code and run `/mcp` to verify the server shows as connected.
> **Note**: Don't commit `.mcp.json` if it contains secrets — add it to `.gitignore`.
### Usage with Other MCP Clients
Export the environment variables before running:
```bash
export LIGHTDASH_TOKEN="ldt_your_token_here"
export LIGHTDASH_URL="https://app.lightdash.cloud"
lightdash-mcp
```
## Available Tools
### 📊 Discovery & Metadata
| Tool | Description |
| :--- | :--- |
| `list-projects` | List all available Lightdash projects |
| `get-project` | Get detailed information about a specific project |
| `list-explores` | List all available explores/tables in a project |
| `get-explore-schema` | Get detailed schema for a specific explore (dimensions, metrics, joins) |
| `list-spaces` | List all spaces (folders) in the project |
| `get-custom-metrics` | Get custom metrics defined in the project |
### 📈 Chart Management
| Tool | Description |
| :--- | :--- |
| `list-charts` | List all saved charts, optionally filtered by name |
| `search-charts` | Search for charts by name or description |
| `get-chart-details` | Get complete configuration of a specific chart |
| `create-chart` | Create a new saved chart with metric query and visualization config |
| `update-chart` | Update an existing chart's configuration (name, description, queries, visualization) |
| `run-chart-query` | Execute a chart's query and retrieve the data |
| `delete-chart` | Delete a saved chart |
### 📋 Dashboard Management
| Tool | Description |
| :--- | :--- |
| `list-dashboards` | List all dashboards in the project |
| `create-dashboard` | Create a new dashboard (empty or with tiles) |
| `duplicate-dashboard` | Clone an existing dashboard with a new name |
| `get-dashboard-tiles` | Get all tiles from a dashboard with optional full config |
| `get-dashboard-tile-chart-config` | Get complete chart configuration for a specific dashboard tile |
| `get-dashboard-code` | Get the complete dashboard configuration as code |
| `create-dashboard-tile` | Add a new tile (chart, markdown, or loom) to a dashboard |
| `update-dashboard-tile` | Update tile properties (position, size, content) |
| `rename-dashboard-tile` | Rename a dashboard tile |
| `delete-dashboard-tile` | Remove a tile from a dashboard |
| `update-dashboard-filters` | Update dashboard-level filters |
| `run-dashboard-tiles` | Execute one, multiple, or all tiles on a dashboard concurrently |
### 🔍 Query Execution
| Tool | Description |
| :--- | :--- |
| `run-chart-query` | Execute a saved chart's query and return data |
| `run-dashboard-tiles` | Run queries for dashboard tiles (supports bulk execution) |
| `run-raw-query` | Execute an ad-hoc metric query against any explore |
### 🗂️ Resource Management
| Tool | Description |
| :--- | :--- |
| `create-space` | Create a new space to organize charts and dashboards |
| `delete-space` | Delete an empty space |
## Project Structure
```
.
├── pyproject.toml # Package configuration
├── lightdash_mcp/ # Main package
│ ├── __init__.py # Package init
│ ├── server.py # MCP server entry point
│ ├── lightdash_client.py # Lightdash API client
│ └── tools/ # Tool implementations
│ ├── __init__.py # Auto-discovery and tool registry
│ ├── base_tool.py # Base tool interface
│ └── *.py # Individual tool implementations
├── README.md
└── LICENSE
```
## Development
### Adding a New Tool
The server automatically discovers and registers tools from the `tools/` directory. To add a new tool:
1. **Create a new file** in `lightdash_mcp/tools/` (e.g., `my_new_tool.py`)
2. **Define the tool**:
```python
from pydantic import BaseModel, Field
from .base_tool import ToolDefinition
from .. import lightdash_client as client
class MyToolInput(BaseModel):
param1: str = Field(..., description="Description of param1")
TOOL_DEFINITION = ToolDefinition(
name="my-new-tool",
description="Description of what this tool does",
input_schema=MyToolInput
)
def run(param1: str) -> dict:
"""Execute the tool logic"""
result = client.get(f"/api/v1/some/endpoint/{param1}")
return result
```
3. **Restart the server** - the tool will be automatically registered
### Tool Registry
Tools are automatically discovered via `tools/__init__.py`, which:
* Scans the `tools/` directory for Python modules
* Imports each module (excluding utility modules)
* Registers tools by their `TOOL_DEFINITION.name`
### Testing
You can test individual tools by importing them:
```python
from tools import tool_registry
# List all registered tools
print(tool_registry.keys())
# Test a specific tool
result = tool_registry['list-projects'].run()
print(result)
```
## Troubleshooting
### Authentication Errors
If you see `401 Unauthorized` errors:
* Verify your `LIGHTDASH_TOKEN` is correct and starts with `ldt_`
* Check that the token hasn't expired
* Ensure you have the necessary permissions in Lightdash
### Connection Errors
If you see connection errors:
* Verify `LIGHTDASH_URL` is correct
* For Lightdash Cloud: use `https://app.lightdash.cloud`
* For self-hosted: use `https://your-domain.com`
* If behind Cloudflare Access, ensure `CF_ACCESS_CLIENT_ID` and `CF_ACCESS_CLIENT_SECRET` are set
* If behind Google Cloud IAP, ensure `IAP_ENABLED=true` is set, install with `pip install lightdash-mcp[iap]`, and verify the service account has `serviceAccountTokenCreator` on itself
### Tool Not Found
If a tool isn't showing up:
* Check that the file is in the `tools/` directory
* Ensure the file has a `TOOL_DEFINITION` variable
* Verify the file isn't in the exclusion list in `tools/__init__.py`
* Restart the MCP server
## Contributing
Contributions are welcome! Please:
1. Fork the repository
2. Create a feature branch
3. Add your changes with appropriate tests
4. Submit a pull request
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Support
For issues and questions:
* [Lightdash Documentation](https://docs.lightdash.com/)
* [Lightdash Community Slack](https://join.slack.com/t/lightdash-community/shared_invite/)
* [MCP Documentation](https://modelcontextprotocol.io/)
TDQS
Scored across 28 tools
Most tools have clearly distinct purposes, such as create/list/get/update/delete for charts, dashboards, and spaces. However, there is potential confusion between run-chart-query and run-raw-query, and between get-dashboard-code, get-dashboard-tiles, and get-dashboard-tile-chart-config, though descriptions mitigate ambiguity.
All tool names follow a consistent verb-noun pattern with hyphens (e.g., create-chart, list-dashboards, get-explore-schema). No mixing of conventions like camelCase or snake_case, making the pattern predictable.
28 tools is on the higher side but well-justified for a BI server covering charts, dashboards, spaces, explores, queries, and projects. The count reflects comprehensive coverage without being bloated; each tool earns its place.
The tool set covers CRUD operations for charts, dashboards, spaces, explores, and queries, supporting a full lifecycle. Minor gaps include no general dashboard rename tool (though duplicate-dashboard helps) and no bulk operations, but core workflows are well-supported.