Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ That's why ERD Studio exists.

## The solution

ERD Studio is a **free, AI-native alternative** that puts the semantic model in the **same repo as the SQL**, as a visual canvas both you and the AI can read and write.
ERD Studio is a **free and open source, AI-native alternative** that puts the semantic model in the **same repo as the SQL**, as a visual canvas both you and the AI can read and write.

Under the hood, your model is plain YAML and JSON — AI reads it natively, git diffs it cleanly, and the canvas is just the human-readable view. No proprietary format, no lock-in.

Expand Down Expand Up @@ -335,6 +335,6 @@ That's the whole system. Three folders, two file types, one diagram per JSON, on
---

<p align="center">
<sub>MIT License &bull; Made for the dbt community</sub><br />
<sub><a href="https://github.com/liam-machine/erd-studio/issues">Report a bug</a> &bull; <a href="https://github.com/liam-machine/erd-studio/discussions">Start a discussion</a></sub>
<sub>Open source (MIT) &bull; Made for the dbt community</sub><br />
<sub><a href="https://github.com/liam-machine/erd-studio">View source</a> &bull; <a href="https://github.com/liam-machine/erd-studio/issues">Report a bug</a> &bull; <a href="https://github.com/liam-machine/erd-studio/discussions">Start a discussion</a></sub>
</p>
3 changes: 3 additions & 0 deletions mcp-server/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
dist/
*.log
21 changes: 21 additions & 0 deletions mcp-server/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Liam Wynne

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
110 changes: 110 additions & 0 deletions mcp-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# erd-studio-mcp

[![npm version](https://img.shields.io/npm/v/erd-studio-mcp.svg)](https://www.npmjs.com/package/erd-studio-mcp)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

**MCP server for [ERD Studio](https://github.com/liam-machine/erd-studio)** — gives Claude, Cursor, Continue, Zed, or any [Model Context Protocol](https://modelcontextprotocol.io) client **read-only** access to your dbt project's semantic ERD model.

Once installed, your AI assistant can answer questions like:
- *"What domains exist in this dbt project?"*
- *"Show me every model in the `customer-360` domain and how they relate."*
- *"What's the grain of `dim_customer`? What's the design rationale?"*
- *"Which dbt models have `unique` tests but aren't in any ERD?"*

…without you re-explaining your data model in every prompt.

## Read-only by design — for edits, use the VS Code extension

This MCP server is intentionally read-only. For **designing new ERDs, adding models, drawing relationships, generating dbt SQL + schema YAML**, install the [ERD Studio VS Code extension](https://marketplace.visualstudio.com/items?itemName=liamwynne.erd-studio). The extension ships with an AI coding skill (`.claude/skills/erd-studio/SKILL.md` for Claude Code, equivalents for Copilot / Gemini / Codex) that gives your assistant **full read+write access** via its native file-editing tools — multi-file edits, refactor-style changes, complete schema authoring.

**Pick the right tool for the job:**

| Workflow | Tool |
|---|---|
| Inspect an existing model from any MCP client (Claude Desktop, Cursor, Continue, Zed, …) | **This MCP server** |
| Design / edit / build (in Claude Code, Copilot, Gemini, Codex) | **Extension + its skill** |
| Visual canvas editing | **Extension** |

The MCP and the skill are complementary, not redundant. If you're in Claude Code already, the skill does more. If you're not, the MCP at least gets you read access.

If the user asks the AI to design or modify anything, the AI will (via the `get_editor_setup` tool) point them at the extension's install path.

## Install

### Claude Code

```bash
claude mcp add erd-studio -- npx -y erd-studio-mcp
```

### Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
"mcpServers": {
"erd-studio": {
"command": "npx",
"args": ["-y", "erd-studio-mcp"]
}
}
}
```

### Cursor / Continue / Zed

These editors support MCP via their respective config files. Use the same `command`/`args` shape — see your editor's MCP docs.

## Tools

All tools take a `project_path` argument: the **absolute path** to the dbt project root (the directory containing `dbt_project.yml`). The project should also contain an `erd-studio/` directory created by the [ERD Studio VS Code extension](https://marketplace.visualstudio.com/items?itemName=liamwynne.erd-studio).

| Tool | Returns |
|---|---|
| `list_domains` | All ERDs grouped by layer. Filter optional by `layer`. |
| `read_domain` | Full domain: models + columns + relationships + cardinality + rationale. |
| `list_models` | All logical model definitions from `erd-studio/logical-models/*.yml`. |
| `read_model` | Single logical model with column-level metadata, grain, SCD types, rationale. |
| `list_manifest_models` | Models from `target/manifest.json` (what dbt actually built), with unique/relationship test coverage. Filter optional by `name_contains`. |
| `get_editor_setup` | Returns install instructions for the ERD Studio VS Code extension. Use this when the user wants to edit, design, or build (this MCP server is read-only). |

All tools are read-only. If the project hasn't been initialized with an `erd-studio/` directory yet, list-tools return empty results with a `tip` field pointing to the install path; read-tools throw a friendly error doing the same. Either way the AI naturally surfaces the extension install path to the user.

## What the AI gets

Unlike most ERD tools where the model is locked behind a vendor UI, ERD Studio stores the semantic model as **plain YAML + JSON in your dbt repo**. This MCP server exposes that model structurally:

- **Grain** as a first-class field — *"one row per customer (current + history)"*
- **Model role** — `conformed-dim`, `transaction-fact`, `bridge`, etc.
- **SCD type per column** — `0` fixed, `1` overwrite, `2` track history
- **Design rationale** — *why* the model was designed this way
- **Cross-stage drift** — manifest test coverage compared to design intent

So when you ask the AI *"propose a column to add to `dim_customer`"*, it sees not just the column list but the design intent — and produces proposals that align with your modelling style.

## Requirements

- **Node.js ≥ 18**
- A dbt project (containing `dbt_project.yml`)
- *(Optional but recommended)* The [ERD Studio VS Code extension](https://marketplace.visualstudio.com/items?itemName=liamwynne.erd-studio) for creating and editing ERDs visually. The MCP server reads the same files the extension writes.

## Without ERD Studio yet

If your dbt project doesn't have an `erd-studio/` directory yet:

1. Install the [VS Code extension](https://marketplace.visualstudio.com/items?itemName=liamwynne.erd-studio)
2. In VS Code: Command Palette → `dbt: Set Up Semantic Domains Directory`
3. Optionally: Command Palette → `dbt: Install AI Coding Harness` to get the bundled skill

The MCP server still works on uninitialized projects — `list_manifest_models` reads `target/manifest.json` directly, and the other tools return graceful "install the extension to start designing" tips. So you can install this MCP first to inspect what dbt has, then move to the extension for the design work.

## Source

- Main repo: https://github.com/liam-machine/erd-studio
- Server source: [`mcp-server/`](https://github.com/liam-machine/erd-studio/tree/main/mcp-server)
- Issues: https://github.com/liam-machine/erd-studio/issues

## License

MIT — see [LICENSE](https://github.com/liam-machine/erd-studio/blob/main/LICENSE) at the repo root.
44 changes: 44 additions & 0 deletions mcp-server/esbuild.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { build } from 'esbuild';
import { chmodSync } from 'node:fs';

const dirnamePolyfill =
'import { fileURLToPath as __ercfu } from "url"; ' +
'import { dirname as __ercd } from "path"; ' +
'const __filename = __ercfu(import.meta.url); ' +
'const __dirname = __ercd(__filename);';

const requirePolyfill =
'import { createRequire } from "module"; ' +
'const require = createRequire(import.meta.url);';

// Main entry — the MCP stdio server
await build({
entryPoints: ['src/index.ts'],
bundle: true,
platform: 'node',
target: 'node18',
format: 'esm',
outfile: 'dist/index.js',
external: ['@modelcontextprotocol/sdk', 'zod', 'yaml'],
banner: {
js: `#!/usr/bin/env node\n${requirePolyfill} ${dirnamePolyfill}`,
},
logLevel: 'info',
});
chmodSync('dist/index.js', 0o755);

// Manifest worker — bundled separately, spawned by ManifestService via worker_threads
await build({
entryPoints: ['../src/workers/manifestWorker.ts'],
bundle: true,
platform: 'node',
target: 'node18',
format: 'esm',
outfile: 'dist/manifestWorker.js',
banner: {
js: `${requirePolyfill} ${dirnamePolyfill}`,
},
logLevel: 'info',
});

console.log('Built dist/index.js + dist/manifestWorker.js');
Loading
Loading