> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lightdash.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Lightdash MCP server

> Connect Claude, ChatGPT, Codex, and other AI tools to Lightdash over the Model Context Protocol

<Info>
  Available to all Lightdash Cloud users. Self-hosted organizations need an Enterprise license and must [enable MCP](/self-host/enterprise-features/mcp).
</Info>

The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) lets external AI assistants — Claude, ChatGPT, OpenAI Codex, Cursor, VS Code, and custom agents — connect to Lightdash and query your data directly. Lightdash runs the MCP server and your assistant is the client, so it can explore your data models, search for metrics and dimensions, run queries, and surface data-driven insights through natural conversation. MCP uses secure OAuth authentication and respects all your existing access controls, so data stays protected.

<Note>
  This is for pointing an outside assistant **into** Lightdash. To give your Lightdash agents tools from outside services like Notion, Linear, or Confluence, that's the reverse direction — see [Connect external MCP servers](/agents/connect-external-mcp-servers).
</Note>

## Connect a client

Lightdash generates the server URL and configuration for your instance and your client. Open **Settings → MCP → Connect**, pick a client, and copy what it gives you: a command, a config file, or the server URL.

<Steps>
  <Step title="Open Settings → MCP → Connect">
    Any Lightdash user can open it. On a self-hosted instance, it uses your own domain.
  </Step>

  <Step title="Pick your client and copy the configuration">
    Choose Claude Desktop, Claude Code, Codex, Cursor, or VS Code. For ChatGPT or another client that isn't listed, choose **Other clients** for the server URL and the Streamable HTTP and OAuth setup steps.
  </Step>

  <Step title="Authenticate">
    Connect from your client, sign in to Lightdash in your browser, and approve access. To confirm it worked, ask the assistant which Lightdash tools it has, as in [Verifying your MCP connection](#example-1-verifying-your-mcp-connection).
  </Step>
</Steps>

## Manual setup

Every client needs the MCP server URL for your instance and a way to authenticate. Interactive clients use OAuth; headless integrations can use a personal access token. Use this section when you want a client-specific walkthrough, when you're configuring a client without opening Lightdash, or when you're building your own integration.

### Find your instance name

Your instance name is the subdomain of the URL you use to open Lightdash in your browser. Open Lightdash, look at the address bar, and take the part before `.lightdash.cloud`:

| Your Lightdash URL | Instance name | MCP URL |
| - | - | - |
| `https://app.lightdash.cloud/...` | `app` | `https://app.lightdash.cloud/api/v1/mcp` |
| `https://eu1.lightdash.cloud/...` | `eu1` | `https://eu1.lightdash.cloud/api/v1/mcp` |
| `https://acme.lightdash.cloud/...` | `acme` | `https://acme.lightdash.cloud/api/v1/mcp` |

<Note>
  For most Lightdash Cloud users the instance name is `app` or `eu1`. That's expected, not a placeholder you need to change. Only dedicated instances have a company-specific name like `acme`.
</Note>

If you self-host Lightdash on your own domain, the MCP endpoint lives at `https://<your-lightdash-host>/api/v1/mcp` instead. See [MCP for self-hosted instances](/self-host/enterprise-features/mcp).

### Claude.ai and Claude Desktop

Set up MCP in the [Claude.ai](https://claude.ai) web app, and it will automatically sync to your Claude Desktop app after restart.

<Accordion title="Setup instructions">
  1. **Access Settings in Claude.ai**

     Navigate to your profile menu (bottom-left corner) and select Settings.

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/claude-ai-01-click-profile-settings.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=389fda25e5effe37ec285f142eb659d4" alt="Navigate to profile menu in bottom-left corner and click Settings" width="2678" height="1840" data-path="images/agents/lightdash-mcp/claude-ai-01-click-profile-settings.png" />
       </Frame>
  2. **Add Custom Connector**

     In the Settings menu, select "Connectors" from the sidebar, then click "Add custom connector".

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/claude-ai-02-select-connectors-then-add-custom-connector.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=504271c844d9667fd408dca7a4ba7b38" alt="Select Connectors from the sidebar menu, then click Add custom connector button" width="2678" height="1840" data-path="images/agents/lightdash-mcp/claude-ai-02-select-connectors-then-add-custom-connector.png" />
       </Frame>
  3. **Configure Connection**

     Fill in the connection details with your Lightdash instance information.

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/claude-ai-03-fill-out-name-and-mcp-url.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=f9e2798da9e4004a27759fcf96285152" alt="Enter Lightdash as the name and your instance MCP URL in the configuration form" width="2678" height="1840" data-path="images/agents/lightdash-mcp/claude-ai-03-fill-out-name-and-mcp-url.png" />
       </Frame>

     * **Name:** Lightdash (or any name you prefer)
     * **URL:** `https://<your_instance_name>.lightdash.cloud/api/v1/mcp` (commonly `app` or `eu1`, see [Find your instance name](#find-your-instance-name))
  4. **Connect and Authenticate**

     Click the "Connect" button to initiate the authentication process.

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/claude-ai-04-click-connect.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=20c36144297f0bf0544116043f6ccadb" alt="Click the Connect button to start OAuth authentication with Lightdash" width="2678" height="1840" data-path="images/agents/lightdash-mcp/claude-ai-04-click-connect.png" />
       </Frame>
  5. **Complete OAuth Flow**

     Log in to your Lightdash account and approve the connection when prompted.

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/claude-ai-05-oauth-flow-via-lightdsah.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=50c9d37b1bd007ee4480584e71ad3378" alt="Login to Lightdash with your credentials and approve the OAuth connection request" width="2678" height="1840" data-path="images/agents/lightdash-mcp/claude-ai-05-oauth-flow-via-lightdsah.png" />
       </Frame>
  6. **Configure Permissions (Optional)**

     Optionally configure which MCP tools Claude can access and set any additional permissions.

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/claude-ai-06-OPTIONAL-configure.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=f05826ff8e44f3952299f80e2bbd2b35" alt="Optional: Configure MCP tool access and permissions for your Claude assistant" width="2494" height="1872" data-path="images/agents/lightdash-mcp/claude-ai-06-OPTIONAL-configure.png" />
       </Frame>
</Accordion>

### ChatGPT

ChatGPT connects to remote MCP servers through custom connectors.

<Accordion title="Setup instructions">
  1. **Open ChatGPT settings**

     Open your profile menu and select **Settings**.

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/chatgpt-01-click-profile-settings.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=d8ca6d50c0c9ef8ee1c389bba4585775" alt="ChatGPT profile menu with Settings highlighted" width="2618" height="1880" data-path="images/agents/lightdash-mcp/chatgpt-01-click-profile-settings.png" />
       </Frame>
  2. **Create a connector**

     Select **Connectors**, then click **Create**.

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/chatgpt-02-select-connectors-then-create.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=71fd01d56b7e746cca3e173542370cc5" alt="ChatGPT Connectors settings with the Create button highlighted" width="2618" height="1880" data-path="images/agents/lightdash-mcp/chatgpt-02-select-connectors-then-create.png" />
       </Frame>
  3. **Configure the connector**

     Enter the connection details, confirm that you trust the application, then click **Create**.

     * **Name:** Lightdash
     * **Description:** Query data and explore existing charts and dashboards in Lightdash
     * **MCP server URL:** `https://<your_instance_name>.lightdash.cloud/api/v1/mcp`
     * **Authentication:** OAuth

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/chatgpt-03-fill-out-name-desc-mcp-url-select-oauth.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=06b5896a61be89e614f3d3958c68879f" alt="ChatGPT connector form configured with the Lightdash MCP URL and OAuth authentication" width="2618" height="1880" data-path="images/agents/lightdash-mcp/chatgpt-03-fill-out-name-desc-mcp-url-select-oauth.png" />
       </Frame>
  4. **Approve access**

     Sign in to Lightdash and approve the connection.

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/chatgpt-04-oauth-flow-via-lightdsah.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=b17322d71f52d6e705da84f52166ae2b" alt="Lightdash authorization screen for approving the ChatGPT connector" width="2618" height="1880" data-path="images/agents/lightdash-mcp/chatgpt-04-oauth-flow-via-lightdsah.png" />
       </Frame>
</Accordion>

### Claude Code

For developers using Claude Code CLI:

```bash theme={null}
claude mcp add --transport http lightdash 'https://<your_instance_name>.lightdash.cloud/api/v1/mcp'
```

Replace `<your_instance_name>` with your actual Lightdash instance name (commonly `app` or `eu1`, see [Find your instance name](#find-your-instance-name)).

<Accordion title="Setup instructions">
  1. **Use the /mcp command in Claude Code**

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/claude-code-01-slash-mcp-command.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=735dabc9e72b80a8a8d573ce305bc58e" alt="Type /mcp to see available MCP connections" width="2634" height="1300" data-path="images/agents/lightdash-mcp/claude-code-01-slash-mcp-command.png" />
       </Frame>
  2. **Select Lightdash from the list**

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/claude-code-02-select-lightdash-navigating-using-arrow-keys.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=7f462a7709c2c4eae70b9061d5e4af94" alt="Navigate to Lightdash using arrow keys" width="2634" height="1300" data-path="images/agents/lightdash-mcp/claude-code-02-select-lightdash-navigating-using-arrow-keys.png" />
       </Frame>
  3. **Authenticate with Lightdash**

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/claude-code-03-select-authenticate-hit-enter.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=c7cbc994e0953334f640b593b8ed8fb4" alt="Select Authenticate and hit Enter" width="2634" height="1300" data-path="images/agents/lightdash-mcp/claude-code-03-select-authenticate-hit-enter.png" />
       </Frame>
  4. **Complete OAuth Flow**

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/claude-code-04-complete-oauth-flow-via-lightdash.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=b0bd1d41ea57d696c41c0f3724b929ea" alt="Complete the OAuth flow via Lightdash" width="2408" height="1476" data-path="images/agents/lightdash-mcp/claude-code-04-complete-oauth-flow-via-lightdash.png" />
       </Frame>
  5. **Start using MCP**

       <Frame>
         <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/claude-code-05-start-prompting-after-successful-auth.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=f1d0417bdb893f5606c27766b372c2e9" alt="Start prompting after successful authentication" width="2634" height="1802" data-path="images/agents/lightdash-mcp/claude-code-05-start-prompting-after-successful-auth.png" />
       </Frame>

  After authentication, you can start asking questions about your Lightdash data directly in Claude Code!
</Accordion>

### Codex

Add the server and start the sign-in flow from your terminal:

```bash theme={null}
codex mcp add lightdash --url 'https://<your_instance_name>.lightdash.cloud/api/v1/mcp'
codex mcp login lightdash
```

Replace `<your_instance_name>` with your actual Lightdash instance name. Sign in to Lightdash in your browser, approve access, then start a new Codex session.

### Cursor

Add the server to your project's `.cursor/mcp.json`:

```json theme={null}
{
  "mcpServers": {
    "lightdash": {
      "url": "https://<your_instance_name>.lightdash.cloud/api/v1/mcp"
    }
  }
}
```

Open **Cursor Settings → MCP & Integrations**, connect Lightdash, then sign in and approve access in your browser.

<Frame>
  <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/CleanShot2025-08-28at17.42.54@2x.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=9659b63a4d0fa6f82af9b67e7b5776b9" alt="Cursor MCP and integrations settings showing the Lightdash server" width="1630" height="1038" data-path="images/agents/lightdash-mcp/CleanShot2025-08-28at17.42.54@2x.png" />
</Frame>

### VS Code

Add the server to your project's `.vscode/mcp.json`:

```json theme={null}
{
  "servers": {
    "lightdash": {
      "type": "http",
      "url": "https://<your_instance_name>.lightdash.cloud/api/v1/mcp"
    }
  }
}
```

Run **MCP: List Servers** from the Command Palette, select Lightdash, and start it. Sign in when prompted, then use the tools in Copilot agent mode.

### Custom integrations

If you're building your own agents or automated workflows, you can integrate directly with Lightdash MCP:

* **Transport**: Lightdash MCP exposes a Streamable HTTP transport endpoint at `https://<your_instance_name>.lightdash.cloud/api/v1/mcp`
* **Debugging**: Use `@modelcontextprotocol/inspector` to inspect and debug the MCP connection
* **Authentication**: For interactive setups use OAuth 2.0. For headless agents and automated workflows, you can authenticate with a Personal Access Token by passing it in the `Authorization` header — both `Authorization: ApiKey ldpat_<redacted>` and `Authorization: Bearer ldpat_<redacted>` are accepted on the MCP endpoint and resolve to the same PAT authentication path. The `Bearer` alias is accepted only on the MCP endpoint. Use `Bearer` when your MCP host only supports static `Bearer` tokens (for example, Claude managed agents and other third-party MCP hosts that don't let you choose a custom auth scheme); use `ApiKey` for direct HTTP clients where you can set the scheme yourself, since it makes it explicit that the token is a Lightdash PAT. Create the token under **Settings → Personal access tokens** for the user whose permissions and attributes you want the integration to use. Service account tokens are also supported on plans that include them.
* **Redirect URIs**: A wildcard in a registered redirect URI matches only a port, a path, or one leftmost subdomain label, for example `https://*.example.com/callback`. Lightdash refuses a redirect URI that has a user name, a password or a backslash. When the agent identity feature flag is on, stricter rules apply. See [OAuth with agent identity on](#oauth-with-agent-identity-on).
* **Documentation**: See the [MCP specification](https://modelcontextprotocol.io/docs) for implementation details
* **Pin a project (optional)**: pass `X-Lightdash-Project: <project-uuid>` to scope the MCP session to a specific project, skipping the `set_project` step. See [details below](#pin-a-project-with-the-x-lightdash-project-header).
* **Override user attributes per request (optional)**: pass `X-Lightdash-User-Attributes: <json>` to override the authenticated user's attributes for that request (useful for row-level security when an agent acts on behalf of different end-users). See [details below](#override-user-attributes).

#### OAuth with agent identity on

When the [agent identity](/agents/agent-identity) feature flag is on, the Lightdash OAuth server is stricter. A custom OAuth client must:

* **Send the `resource` parameter** set to the MCP URL, for example `https://<your_instance_name>.lightdash.cloud/api/v1/mcp`. Each token is for the Lightdash API or for MCP, and one audience refuses the other's tokens. Without `resource`, the token is for the API, so the MCP endpoint refuses it.
* **Register exact redirect URIs.** Only an http loopback redirect (`localhost`, `127.0.0.1` or `[::1]`) can use a different port. Allowed schemes are https, http on a loopback host, reverse-DNS native schemes such as `com.example.app`, and `cursor`, `vscode`, `vscode-insiders`, `windsurf` and `lightdash`. Dynamic client registration refuses wildcards, except for the loopback port.
* **Use PKCE with `S256`.**
* **Send the token in the `Authorization` header.** Lightdash refuses a bearer token in the query string.

Use each refresh token once. When a used refresh token comes back, Lightdash revokes every token from that sign-in. Authorization responses also include the `iss` parameter (RFC 9207).

<a id="pin-a-project-with-the-x-lightdash-project-header" />

#### Pin a project with the `X-Lightdash-Project` header

By default, MCP clients use `set_project` to choose an active project, and the selection is stored as a per-user context. If you're building an integration that should always operate against a single project, you can pre-select the project by sending the `X-Lightdash-Project` header on every request to `/api/v1/mcp`.

When the header is set:

* The project UUID in the header is used as the active project for that request, overriding any project previously set with `set_project`.
* The `list_projects` and `set_project` tools are hidden from `tools/list`, so the AI assistant can't change the project for the request.
* Access to the project is still enforced by your user, API key, or service account's permissions — the header can't be used to access projects the caller can't already see.

This is useful when you want each integration, workspace, or environment to be locked to one project (for example, a separate connector per project) without relying on the AI assistant to call `set_project` first.

The header value must be a valid project UUID. You can find the project UUID in the Lightdash URL when viewing a project (`/projects/<projectUuid>/...`).

<CodeGroup>
  ```json Cursor (.cursor/mcp.json) theme={null}
  {
    "mcpServers": {
      "lightdash-sales": {
        "url": "https://<your_instance_name>.lightdash.cloud/api/v1/mcp",
        "headers": {
          "X-Lightdash-Project": "00000000-0000-0000-0000-000000000000"
        }
      }
    }
  }
  ```

  ```bash curl theme={null}
  curl https://<your_instance_name>.lightdash.cloud/api/v1/mcp \
    -H "Authorization: Bearer <your_token>" \
    -H "X-Lightdash-Project: 00000000-0000-0000-0000-000000000000" \
    -H "Content-Type: application/json" \
    -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
  ```
</CodeGroup>

<Info>
  If the header value isn't a valid UUID, it's ignored and the request falls back to the user's stored project context. Permissions are always checked against the resolved project, so a header for a project the caller can't view will return a "no access" error.
</Info>

<a id="override-user-attributes" />

#### Override user attributes with the `X-Lightdash-User-Attributes` header

The `X-Lightdash-User-Attributes` header overrides the authenticated user's Lightdash user attributes for that specific MCP request. This is designed for agents that act on behalf of multiple end-users with row-level security: one PAT (or service account) user handles all requests, and per-request RLS scoping is applied via the header.

<Info>
  The PAT or service account user must have the **org admin** role to use this header. Non-admins will receive a `ForbiddenError`.
</Info>

The header value must be a JSON object where each value is either a string or an array of strings. For example:

* `{"user_id": "abc123"}`
* `{"user_id": ["abc123", "def456"]}`

<Info>
  If the agent user already has a value set for an attribute, the header can only **narrow** that value (set a subset of the pre-configured values), not expand access. If no value is pre-configured for the attribute on the agent user, any value can be set via the header.
</Info>

<CodeGroup>
  ```bash curl theme={null}
  curl https://<your_instance_name>.lightdash.cloud/api/v1/mcp \
    -H 'Authorization: ApiKey <your_token>' \
    -H 'X-Lightdash-User-Attributes: {"user_id": "abc123"}' \
    -H 'Content-Type: application/json' \
    -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
  ```

  ```json Cursor (.cursor/mcp.json) theme={null}
  {
    "mcpServers": {
      "lightdash-agent": {
        "url": "https://<your_instance_name>.lightdash.cloud/api/v1/mcp",
        "headers": {
          "X-Lightdash-User-Attributes": "{"user_id": "abc123"}"
        }
      }
    }
  }
  ```
</CodeGroup>

<Info>
  Setting the header statically in an MCP client config is suitable for development and testing. For production, where the attribute needs to change per end-user, the calling application must set the `X-Lightdash-User-Attributes` header programmatically on each request.
</Info>

## Network requirements

If your organization uses a corporate firewall, VPN, or internet security tool, the following domains must be allowlisted for MCP to work correctly:

| Domain | Purpose |
| - | - |
| `<your_instance_name>.lightdash.cloud` | Lightdash API and OAuth authentication |
| `claudemcpcontent.com` | Used by Claude to render visual content (charts, tables) from MCP connectors |

<Warning>
  If `claudemcpcontent.com` is blocked, Claude will still return query results as text but will not be able to display Lightdash visual charts. You may see the error: *"Failed to set up MCP app. Check that claudemcpcontent.com is not blocked by your network or browser."*
</Warning>

If you're having trouble, try opening Claude in an incognito or private browser window to rule out browser extensions such as ad blockers that may be blocking these domains.

## What it can do

### Core capabilities

MCP provides AI assistants with powerful tools to interact with your Lightdash data:

#### Project management

* **List projects** - View all accessible projects in your organization
* **Set active project** - Switch context between different projects (required before accessing any data). Accepts an optional `tags` array to filter the explores and fields visible in the session to those matching the given tags — the same tag-based filtering used by [AI agents](/agents/data-access#limiting-access-to-specific-explores-and-fields), but available directly in an MCP session without needing an agent. Useful when tags work in the Lightdash UI but you also want to scope an MCP session to a specific domain (e.g., `["sales"]`).
* **Get current project** - Check which project is currently active

<Info>
  An active project must be set before MCP can retrieve any data. Your AI assistant will typically handle this automatically by listing available projects and asking you to select one.
</Info>

#### Data exploration

* **List explores** - See all available data models in the current project at a glance
* **Find explores** - Search for relevant data models using natural language (e.g., "customer orders")
* **Find fields** - Search for specific metrics and dimensions by business terms (e.g., "total revenue", "order date")
* **Search field values** - Look up valid values for a field, useful for building filters
* **Find content** - Search for existing spaces, charts, and dashboards by name or description. Results include space breadcrumbs and direct links. Optionally scope the search to a single space (and its descendants) by passing a space slug.
* **List content** - Browse accessible content as a hierarchy. By default it returns root-level spaces; pass a space slug to list the charts, dashboards, and nested spaces directly inside that space. Use this when you want the agent to walk space → content rather than search by keyword.
* **List verified content** - Discover charts and dashboards that admins have marked as verified, so agents can reference trusted, canonical patterns when building new content. If you want your agent to prefer verified patterns, ask it to in your prompt (e.g. *"Use verified charts as the reference for any new chart you build."*).

#### Query execution

* **Run metric query** - Execute queries using your semantic layer's metrics and dimensions. Completed results include a best-effort `exploreUrl` so you can open the query in Lightdash to keep exploring.
* **Render chart** - Render a visualization (tables, bar charts, line charts, pie charts, and more) for a completed metric query result in MCP App-capable clients (e.g., Claude). Call this after a metric query finishes when you want a visual chart; the query is not re-executed. SQL Runner results are not supported by `render_chart`.
* **Run SQL** - Execute arbitrary SQL queries directly against the project's data warehouse. Useful for ad-hoc analysis or queries that don't fit the explore-based model. Returns up to 500 rows by default (configurable up to 5,000). Completed results include a best-effort `sqlRunnerUrl` so you can open the compiled SQL in [SQL Runner](/explore/sql-runner).
* **Get query result** - Poll for the result of a long-running query. If `run_metric_query` or `run_sql` doesn't finish within its wait window, the tool returns a `queryUuid` and the assistant polls `get_query_result` until the warehouse completes the query — so long queries don't time out the session.

<Info>
  **Run SQL** requires the `manage SqlRunner` permission. The SQL is executed directly against your warehouse, so use the appropriate SQL dialect for your connection (e.g., PostgreSQL, BigQuery, Snowflake).
</Info>

<Accordion title="run_sql response shape (for developers)">
  When you call `run_sql` from a custom MCP client or live artifact, the tool returns both a CSV text payload and a `structuredContent` object. Prefer `structuredContent.rows` over parsing the CSV — values arrive as JSON-serializable primitives (numbers, strings, booleans, ISO date strings, or `null`), so you don't need `parseFloat` or `parseInt` on numeric columns.

  **Response envelope:**

  ```json theme={null}
  {
    "content": [
      { "type": "text", "text": "<CSV string with header row + data rows>" }
    ],
    "structuredContent": {
      "rows": [
        { "status": "completed", "n": 94, "total_amount": 2397 }
      ],
      "columns": ["status", "n", "total_amount"],
      "rowCount": 1,
      "sqlRunnerUrl": "https://<your_instance_name>.lightdash.cloud/projects/<project-uuid>/sql-runner?..."
    }
  }
  ```

  **Example usage:**

  ```ts theme={null}
  const result = await callMcpTool('run_sql', { sql, limit });
  const rows = result.structuredContent.rows;       // [{ status: 'completed', n: 94, ... }, ...]
  const columns = result.structuredContent.columns; // ['status', 'n', 'total_amount']
  const sqlRunnerUrl = result.structuredContent.sqlRunnerUrl; // shareable link to inspect/edit the SQL in SQL Runner, or null
  ```

  **Notes:**

  * Empty results still return `structuredContent` as `{ rows: [], columns, rowCount: 0, sqlRunnerUrl }` — distinct from a parse failure.
  * `sqlRunnerUrl` is best-effort and may be `null` if the share link cannot be created. It points to the compiled SQL that was executed, which may differ slightly from the SQL you submitted.
  * On error, the response has `isError: true` and `content[0].text` contains the error message; `structuredContent` is omitted.
  * `content[0].text` continues to carry the raw CSV, so existing clients that parse the text payload keep working.
</Accordion>

<Warning>
  **Security best practice:** Ensure the database credentials configured in your Lightdash connection have **read-only (viewer) access** to your warehouse. Since `run_sql` executes arbitrary SQL, a connection with write permissions could allow AI agents to modify or delete warehouse data.
</Warning>

#### Editing content

MCP can read, create, and edit Lightdash charts and dashboards using the same [content-as-code](/workflow/content-as-code) payloads that the Lightdash CLI uses. This lets agents make targeted edits to existing content or build new charts and dashboards directly in a conversation, without downloading YAML files locally.

* **Read content** (`read_content`) - Fetch a chart or dashboard as JSON by slug. Call this before editing so the agent can see the current state.
* **Edit content** (`edit_content`) - Apply an [RFC 6902 JSON Patch](https://datatracker.ietf.org/doc/html/rfc6902) to an existing chart or dashboard, then validate and persist. Use this for surgical changes (e.g. rename a field, add a filter, swap a chart color) without rewriting the whole object.
* **Create content** (`create_content`) - Create a new chart or dashboard from a full chart-as-code or dashboard-as-code object. Returns the persisted slug and URL.

These tools reuse the same permissions, validation, and project context as the [Lightdash CLI](/workflow/cli/install) `download` and `upload` commands, so the user driving the MCP session needs the same access required to manage that content in Lightdash.

When the `documents` feature flag is on, the same three tools also handle [documents](/explore/documents):

* `read_content` returns the document's ordered cells (Markdown and chart-as-code charts) and its current `versionUuid`.
* `create_content` with `type: "document"` takes a name, slug, description, space slug, and the ordered cells.
* `edit_content` takes a `documentEdit` instead of a JSON Patch. Either replace the whole content, passing the `versionUuid` you read as `baseVersionUuid` and every cell to keep, or update the name, slug, or description on their own. If someone saved the document after you read it, the edit is rejected; read it again and retry. Each content edit saves a new version.

<a id="editing-the-dbt-project" />

#### Editing project models

MCP exposes [AI writeback](/agents/ai-writeback) — editing the dbt or native Lightdash YAML project that backs the active Lightdash project and opening a pull request with the change — to any MCP client. Ask the assistant to rename a metric, add a dimension, edit field SQL, or fix a YAML description; the assistant calls the tools below and hands back a pull request URL when the run finishes. The [AI writeback prerequisites](/agents/ai-writeback#prerequisites) — supported Git host, repository access, and project Developer permission — apply to the MCP surface too.

* **Run AI writeback** (`run_ai_writeback`) - Start a writeback run against the active project's repository from a natural-language prompt. The repository, project directory, and semantic layer format are resolved server-side from the saved connection — you don't specify them. Returns immediately with an `aiWritebackRunUuid`.
* **Get AI writeback status** (`get_ai_writeback_status`) - Poll a writeback run by id. Returns the current pipeline stage while the run is in flight, and the pull request URL (or an error message) once it reaches a terminal state.

##### How the async flow works

A writeback run typically takes a few minutes — longer than most MCP transports will hold a connection open — so `run_ai_writeback` enqueues the run to a background worker and returns immediately with a run id. The caller then polls `get_ai_writeback_status` for the outcome. See [How it works](/agents/ai-writeback#how-it-works) for what the run itself does.

Polling has no session affinity — you can call `get_ai_writeback_status` from a different MCP session or a different API token, as long as the caller has view access to the project the run belongs to. This makes the pair usable from short-lived automations and shell scripts, not just interactive chat clients.

<Info>
  The in-product AI writeback chat card is unaffected by this split: the chat continues to auto-update once the background run finishes, without you polling anything.
</Info>

##### `run_ai_writeback` — start a run

**Parameters**

* `prompt` *(string, required)* — A clear, self-contained description of the change to make to the dbt project (for example, *"Add a `total_revenue` metric to the orders model as the sum of amount"*). When the project has more than one dbt source, name the intended source in the prompt itself (for example, *"In the marketing dbt project, ..."*) — the run reports the available sources back through `get_ai_writeback_status` if it can't tell which one you meant.

**Response** (`structuredContent`)

```json theme={null}
{
  "aiWritebackRunUuid": "b3f4e0e2-8a2b-4d5f-9a1f-1c2d3e4f5a6b"
}
```

<Warning>
  **Breaking change (July 2026).** `run_ai_writeback` used to block until the pipeline finished and return `{ output, exitCode, prUrl }` inline. It now returns `{ aiWritebackRunUuid }` and callers must poll `get_ai_writeback_status` for the pull request URL. External MCP clients hardcoded against the old synchronous shape need to update; the in-product chat is unaffected. This change decouples the run from the MCP transport (so transport idle timeouts can no longer drop a completed run) and removes the naive-retry duplicate-PR risk that came with a synchronous return.
</Warning>

##### `get_ai_writeback_status` — poll for the result

**Parameters**

* `aiWritebackRunUuid` *(UUID, required)* — The id returned by `run_ai_writeback`.

**Response** (`structuredContent`)

```json theme={null}
{
  "status": "ready",
  "prUrl": "https://github.com/acme-analytics/jaffle-shop/pull/482",
  "errorMessage": null
}
```

* `status` is either `"pending"` (not yet picked up by a worker), an in-progress pipeline stage (for example, `"sandbox"`, `"agent"`, or `"pull_request"`), or a terminal value: `"ready"` (finished — check `prUrl`) or `"error"` (finished — check `errorMessage`).
* `prUrl` is set once `status` is `"ready"` and the agent changed at least one file. If the agent decided no change was needed, `status` is still `"ready"` but `prUrl` is `null`.
* `errorMessage` is set once `status` is `"error"`. This also covers the "more than one dbt source" case — the message lists the available sources so the caller can re-run `run_ai_writeback` naming the intended one in the prompt.

Poll every 10-15 seconds rather than tight-looping — a run typically takes a few minutes to finish, and the status row updates in stages rather than continuously.

**Example poll loop**

```ts theme={null}
const { aiWritebackRunUuid } = (
  await callMcpTool('run_ai_writeback', {
    prompt: 'Add a total_revenue metric to the orders model as the sum of amount.',
  })
).structuredContent;

while (true) {
  const { status, prUrl, errorMessage } = (
    await callMcpTool('get_ai_writeback_status', { aiWritebackRunUuid })
  ).structuredContent;

  if (status === 'ready') {
    console.log(prUrl ? `PR opened: ${prUrl}` : 'No file changes were needed.');
    break;
  }
  if (status === 'error') {
    throw new Error(errorMessage ?? 'Writeback failed');
  }

  await new Promise((r) => setTimeout(r, 10_000));
}
```

<Info>
  **Who can write content over MCP.** Organization admins control the feature for everyone from **Settings → MCP → General** with **Allow content changes via MCP**, which is **on by default**. When it's off, `create_content` and `edit_content` are not registered for any MCP client in the organization — reading content over MCP is unaffected.

  When it's on, the two tools are also gated on the caller's role holding the `create:ContentAsCode` scope. That check runs at tool registration, so users without the scope don't see these tools in the tools list.

  * **Roles that get the scope by default:** Editors, Developers, Admins.
  * **Roles that don't:** Interactive Viewers, Viewers.
  * **Custom roles:** must add `create:ContentAsCode` explicitly — see [custom roles](/workspace-admin/custom-roles).

  Project, space, and content-level checks still run at invocation time on top of the registration gate.
</Info>

When prompting an agent to build content, ask it to use [verified content](#data-exploration) as a reference. The agent can call `find_content` and `read_content` on a verified chart, then use that JSON as the template for `create_content`, so what it saves follows the patterns your team has already approved.

**Example prompt:** *"Read the `weekly-revenue` chart, then create a copy called `weekly-revenue-by-region` that adds `customers_region` as a pivot dimension."*

The assistant will call `read_content` to fetch the source chart, modify the JSON to add the pivot, and call `create_content` to save the new chart — returning a link to open it in Lightdash.

<Tip>
  For bulk edits across many dashboards or as part of a CI/CD pipeline, the [download-edit-upload workflow](/workflow/edit-dashboards-with-agents) using the Lightdash CLI is still the recommended approach. MCP content tools are best for interactive edits inside an AI assistant.
</Tip>

#### Data app builds

MCP can build [data apps](/data-apps) — interactive applications generated from a brief on top of the active project's semantic layer — from any MCP client. Ask the assistant to build an app, wait a few minutes while it builds, then iterate on it with follow-up briefs. Each build adds a **version** to the app.

* **Generate data app** (`generate_data_app`) - Start building a new app from a name and a brief. Optionally start from an existing dashboard or saved charts, pick a starter template, or apply a theme.
* **Iterate data app** (`iterate_data_app`) - Build a new version of an existing app from a follow-up brief. The app keeps its name, slug, and theme unless you ask for a different theme.
* **List data app themes** (`list_data_app_themes`) - List the organization's [themes](/data-apps/customize-themes) so the assistant can apply one when it builds.
* **Get data app build status** (`get_data_app_build_status`) - Check how a build is going, and get the app's URL once it's ready. The assistant checks this for you while the build runs.

Builds run in the background, so the assistant reports that the build has started and then follows up when it's ready. Once it is, the assistant can open the app for you, read it back with `read_content`, or keep iterating.

An app built over MCP is created as the calling user's **personal app**: at the project root, in no space, visible only to them until they move it into a space from the Lightdash UI. This mirrors what the in-product [AI agent](/agents) does.

<Info>
  **What enables these tools.** The data app tools only appear in the tools list when both of these are true:

  1. Data apps are enabled for your organization.
  2. The caller can create data apps in the active project.
</Info>

**Example prompts:**

* *"Build a data app called Revenue Overview that shows monthly revenue and the top 10 customers, then tell me when it's ready."*
* *"Add a region filter to the Revenue Overview app."*

#### Scheduled deliveries

* **Create scheduled delivery** (`create_scheduled_delivery`) - Schedule an existing chart or dashboard to Slack, email, or another supported destination on a cron schedule. Point the tool at the content by slug and pass the schedule and recipients — the delivery is created against the active project using the caller's permissions.

<Info>
  **What enables this tool.** `create_scheduled_delivery` only appears in the tools list when both of these are true:

  1. **Allow content changes via MCP** is on (**Settings → MCP → General**).
  2. The caller's role holds the `create:ScheduledDeliveries` scope.

  **Roles that get `create:ScheduledDeliveries` by default:** Interactive Viewers, Editors, Developers, Admins. **Viewers** do not. Custom roles must add the scope explicitly.
</Info>

**Example prompt:** *"Set up a scheduled delivery of the `weekly-ecom-orders` chart to #analytics-updates in Slack every Monday at 9am."*

The assistant will call `create_scheduled_delivery` with the chart's slug, the cron schedule, and the Slack destination — mirroring the [AI agent](/agents) `createScheduledDelivery` tool but exposed to any MCP client.

#### Agent context

* **Route agent** - Automatically select and activate the best agent for a user prompt within the active project. This is the preferred way to pick an agent — it mirrors the [AI Router](/agents/enable-ai-router) experience in the Lightdash app, so MCP sessions get the same automatic agent selection.
* **List agents** - Discover available AI agents and their areas of expertise
* **Set agent** - Manually activate an agent to scope your session to its explores, instructions, and verified answers. Use this when you want to override automatic routing.
* **Get current agent** - Check which agent is active and view its full context
* **Clear agent** - Remove agent scoping and return to the full project context

These tools are covered in detail in the [Using AI agent context](#using-ai-agent-context) section below.

<Info>
  When an agent is active, its scope applies to the whole session: data exploration is limited to the agent's explores, and content tools (find, list, read, create, and edit) only see spaces the agent has access to.
</Info>

#### Skills

Lightdash ships built-in skills (such as `developing-in-lightdash`) that give AI assistants guidance for working with Lightdash — for example, conventions for writing dbt models, charts, and dashboards. These skills are exposed as MCP resources, which most clients consume automatically.

Your organization's [custom agent skills](/agents/custom-agent-skills) are available through the same MCP connection. When an AI agent is active in the session, MCP exposes the custom skills attached to that agent. Without an active agent, it exposes the organization skills the caller has permission to view.

For MCP clients that don't read resources directly (e.g. Claude Code), three fallback tools let the assistant discover and load the same content:

* **List skills** (`list_skills`) - Return the available built-in and custom skills along with their supporting resource files
* **Read skill** (`read_skill`) - Read the main `SKILL.md` instructions for a skill by name (e.g. `developing-in-lightdash`)
* **Read skill resource** (`read_skill_resource`) - Read a supporting resource file for a skill by name and resource path (e.g. `resources/dashboard-best-practices.md`)

You don't need to call these tools explicitly — when relevant, the assistant will call `list_skills` to discover what's available and then load the skill content it needs. If your client already supports MCP resources, you can ignore these tools; both paths return the same content.

<Accordion title="Skill resources via MCP (for developers)">
  The Lightdash MCP server exposes built-in and custom skills as MCP resources, so any MCP-compatible client can discover and load them at runtime — no CLI install required.

  The server advertises support via the `io.modelcontextprotocol/skills` extension capability returned from `initialize`. Clients that don't recognize the extension can still list and read the resources directly.

  **Available resources:**

  | URI | Type | Description |
  | - | - | - |
  | `skill://index.json` | `application/json` | Discovery index listing every built-in skill and its supporting files. |
  | `skill://lightdash/<skill-name>/SKILL.md` | `text/markdown` | A skill's instructions and frontmatter (e.g. `skill://lightdash/developing-in-lightdash/SKILL.md`). |
  | `skill://lightdash/<skill-name>/resources/<file>` | `text/markdown` | Supporting reference files for a skill. |
  | `skill://custom/index.json` | `application/json` | Discovery index for the custom skills available to the caller. |
  | `skill://custom/<skill-name>/SKILL.md` | `text/markdown` | A custom skill's instructions and frontmatter. |
  | `skill://custom/<skill-name>/resources/<file>` | `text/markdown` | A custom skill's supporting resource file. |

  **Example: list and read a skill via JSON-RPC**

  ```json theme={null}
  // List available resources
  { "jsonrpc": "2.0", "id": 1, "method": "resources/list", "params": {} }

  // Read the discovery index
  { "jsonrpc": "2.0", "id": 2, "method": "resources/read",
    "params": { "uri": "skill://index.json" } }

  // Read a specific skill
  { "jsonrpc": "2.0", "id": 3, "method": "resources/read",
    "params": { "uri": "skill://lightdash/developing-in-lightdash/SKILL.md" } }
  ```
</Accordion>

<Tip>
  If you're working in Claude Code, Cursor, or another supported editor, you can also [install skills via the CLI](/workflow/install-agent-skills#installing-skills) — it ships the same files to your local agent without requiring an MCP round trip.
</Tip>

### Example conversations

Here are some examples of how you can interact with AI assistants using MCP:

#### Example 1: Verifying your MCP connection

After connecting, verify that the MCP integration is working by asking your AI assistant to list available tools.

**Prompt:** *"What Lightdash tools do you have access to?"*

The assistant will confirm the connection and list the available MCP tools, such as `list_projects`, `find_fields`, `run_metric_query`, `run_sql`, and others. This is a quick way to verify that authentication succeeded and the MCP server is reachable.

<Accordion title="See screenshot">
  <Frame>
    <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/examples-01-verifying-mcp-connection.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=e9d15d5b0eff278fc9f7975302542122" alt="Verifying MCP connection and listing available tools" width="2804" height="2242" data-path="images/agents/lightdash-mcp/examples-01-verifying-mcp-connection.png" />
  </Frame>
</Accordion>

#### Example 2: Setting up a project and finding dashboards

Before querying data, you need to set an active project. Then you can search for existing dashboards and charts.

**Prompt:** *"What projects do I have access to? Set the Jaffle Shop project, then show me all dashboards related to revenue."*

The assistant will:

1. Call `list_projects` to show your available projects
2. Call `set_project` to activate "Jaffle Shop"
3. Call `find_content` with your search term to find matching dashboards and charts

**Expected output:** A list of dashboards and charts matching "revenue", including their names, descriptions, and direct links to view them in Lightdash.

<Accordion title="See screenshot">
  <Frame>
    <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/examples-02-setting-up-project-and-finding-dashboards.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=453b477f2d1e8f625cae58e6ab5d6c32" alt="Setting up project context and finding dashboards" width="2716" height="2466" data-path="images/agents/lightdash-mcp/examples-02-setting-up-project-and-finding-dashboards.png" />
  </Frame>
</Accordion>

#### Example 3: Exploring data and running a metric query

Once a project is active, you can explore data models and run queries using your semantic layer.

**Prompt:** *"What metrics do we have for orders? Show me total revenue by month for the last 6 months as a bar chart."*

The assistant will:

1. Call `find_fields` to search for order-related metrics and dimensions (e.g., `orders_total_revenue`, `orders_order_date`)
2. Call `run_metric_query` with the appropriate explore, metrics, dimensions, filters, and sort order to fetch the data and render a visualization

**Expected output:** A bar chart showing monthly revenue for the last 6 months, along with the underlying data table. The query uses your semantic layer definitions, so metric calculations and joins are handled automatically.

<Accordion title="See screenshot">
  <Frame>
    <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/examples-03-finding-explores-and-fields-and-executing-metric-query-to-analyze-data.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=15986e1986d49e38cb9eaa2e09a974a7" alt="Finding explores and fields, then executing metric queries to analyze data" width="2742" height="2568" data-path="images/agents/lightdash-mcp/examples-03-finding-explores-and-fields-and-executing-metric-query-to-analyze-data.png" />
  </Frame>
</Accordion>

## Using AI agent context

If your organization has [Lightdash AI agents](/agents) configured, you can reuse their configuration in your MCP sessions — so you get consistent guidance regardless of where you're working. Organization admins enable these tools with **Enable agents over MCP** in **Settings → MCP → General**.

### How is this different from Lightdash AI agents?

[Lightdash AI agents](/agents) are a fully managed experience inside Lightdash and Slack. They handle everything end-to-end: interpreting your question, picking the right data, running queries, and presenting results.

With MCP, you can use Lightdash data in other contexts, but the AI assistant driving an MCP session doesn't have the same specialized tuning that Lightdash AI agents provide out of the box. Agent context via MCP bridges that gap: it brings your agents' domain knowledge into any MCP session.

### What you get from agent context

When you activate an agent in your MCP session, your AI assistant receives:

* **[Specialized content](/agents/effective-analytics-with-agents#think-specialized-not-general)**: only the data models relevant to that agent's domain
* **[Verified answers](/agents/verified-answers#how-verified-answers-work)**: curated example queries that demonstrate correct usage of the data model
* **[Custom instructions](/agents/set-up-agents#instructions)**: domain-specific rules like *"Always filter orders by status = 'completed'"*

### Example workflow

1. **Set your project** with `set_project`
2. **Let the router pick an agent** with `route_agent` — pass the user's prompt and Lightdash activates the best-fit agent automatically. Use `list_agents` + `set_agent` only when you want to inspect candidates or override the choice manually.
3. **Ask your questions** — the agent's context automatically guides queries

<Tip>
  `route_agent` chooses between agents the user can already access — it never widens permissions. If only one agent is accessible, it activates that agent directly; if none are accessible, it returns an error so the assistant can fall back to the unscoped project context.
</Tip>

**Prompt:** *"What AI agents are available?"*

<Accordion title="See screenshot: listing agents">
  <Frame>
    <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/examples-04-list-agents.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=366d5d3a544a7c4abdf82ab28d869348" alt="Listing available AI agents in a project" width="870" height="542" data-path="images/agents/lightdash-mcp/examples-04-list-agents.png" />
  </Frame>
</Accordion>

**Prompt:** *"Use the Sales Analyst agent."*

<Accordion title="See screenshot: setting agent and viewing explores">
  <Frame>
    <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/examples-05-set-agent-and-see-explores.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=091816be31928c05296750d4cac37421" alt="Setting an AI agent and viewing its available explores" width="851" height="1031" data-path="images/agents/lightdash-mcp/examples-05-set-agent-and-see-explores.png" />
  </Frame>
</Accordion>

Once an agent is active, your queries automatically follow its instructions. For example, with a Sales Analyst agent configured with these instructions:

```
You are a Sales analyst for Jaffle Shop. Your role is to answer questions
about revenue, orders, customers and subscriptions.

Key guidelines:
- Use the orders explore as the starting point for revenue and order
  volume questions.
- Always include a time dimension when showing trends. Default to monthly
  granularity unless the user specifies otherwise.
- Format currency values in CAD.
```

**Prompt:** *"Can you show me revenue so far?"*

The assistant will automatically use the `orders` explore, include a monthly time dimension, and format values in CAD — all without you specifying these details, because the agent's instructions guide the query.

<Accordion title="See screenshot: querying with agent context">
  <Frame>
    <img src="https://mintcdn.com/lightdash/r5g66-wQ4pdXMZMF/images/agents/lightdash-mcp/examples-06-ask-question-with-agent-context.png?fit=max&auto=format&n=r5g66-wQ4pdXMZMF&q=85&s=dcbc929939693d42b7548753df32ceda" alt="Asking a question with agent context applied for better results" width="782" height="982" data-path="images/agents/lightdash-mcp/examples-06-ask-question-with-agent-context.png" />
  </Frame>
</Accordion>

## Built-in prompt

The Lightdash MCP server includes a built-in **`lightdash-analyst`** prompt with guidelines for querying data effectively. MCP clients that support prompts can use this automatically, so you don't need to configure custom instructions manually.

<Info>
  When an [AI agent](#using-ai-agent-context) is active, the prompt automatically adapts to include the agent's context.
</Info>

## Best practices

To get the most value from MCP, ensure your Lightdash data is well-organized and documented. See our [Effective analytics with agents](/agents/effective-analytics-with-agents) for detailed recommendations on:

* Organizing and naming your data models
* Writing effective documentation and AI hints
* Optimizing for AI assistant performance
* Security and permissions considerations

***

## Lightdash Docs MCP

In addition to the Lightdash data MCP above, we also offer a **Docs MCP endpoint** that gives AI coding agents access to the complete Lightdash documentation. This is free for everyone—including open source users and all cloud tiers.

### Benefits

The Docs MCP helps AI agents:

* Understand Lightdash concepts, configuration, and best practices
* Generate accurate YAML configurations for metrics and dimensions
* Troubleshoot issues using official documentation
* Stay up-to-date with the latest Lightdash features

<Tip>
  For the best experience building and maintaining your semantic layer, we recommend using [agent skills](/workflow/install-agent-skills) instead. Skills provide more targeted context for AI coding agents and are optimized for code generation tasks.
</Tip>

### Setup

The Docs MCP endpoint is available at `https://docs.lightdash.com/mcp`. Add it to your AI coding tool:

<Tabs>
  <Tab title="Cursor">
    Add to your `.cursor/mcp.json`:

    ```json theme={null}
    {
      "mcpServers": {
        "lightdash-docs": {
          "url": "https://docs.lightdash.com/mcp"
        }
      }
    }
    ```
  </Tab>

  <Tab title="Claude Code">
    Run the following command:

    ```bash theme={null}
    claude mcp add --transport http lightdash-docs https://docs.lightdash.com/mcp
    ```
  </Tab>

  <Tab title="Windsurf">
    Add to your `~/.codeium/windsurf/mcp_config.json`:

    ```json theme={null}
    {
      "mcpServers": {
        "lightdash-docs": {
          "serverUrl": "https://docs.lightdash.com/mcp"
        }
      }
    }
    ```
  </Tab>
</Tabs>

### Availability

The Docs MCP is free for everyone:

* Open source users
* Cloud Pro
* Cloud Enterprise

No authentication required.

## FAQ

**Q: Does Lightdash MCP store my data or query results?**

A: No, Lightdash MCP does not store any query results, conversation responses, or data. MCP acts as a bridge that allows AI assistants to access your Lightdash metadata and execute queries in real-time. The MCP consumer (your AI assistant) is responsible for any data storage. Depending on which AI assistant you use, data might be shared with third parties according to their privacy policies.

**Q: Can multiple team members use MCP?**

A: Yes, each team member can set up their own MCP connection with their individual Lightdash credentials. Each connection respects that user's specific permissions and access controls.

**Q: Can MCP modify my data or dashboards?**

A: MCP can create and edit Lightdash charts and dashboards via the [content-as-code tools](#editing-content), and can create [scheduled deliveries](#scheduled-deliveries), when your user account has the required permissions. MCP cannot modify your underlying warehouse data — query execution is read-only (metric queries and SQL `SELECT` only). All write operations respect your existing Lightdash permissions and project access controls, and each write tool is only registered for users whose role grants the corresponding scope.

**Q: Claude returns data as text but no visual chart is displayed. What's wrong?**

A: Claude uses the domain `claudemcpcontent.com` to render visual content from MCP connectors. If this domain is blocked by your corporate firewall, VPN, internet security tool, or a browser extension (like an ad blocker), Claude will fall back to text-only output. See [Network requirements](#network-requirements) above for the full list of domains to allowlist.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.