MCP server that wraps the Dagster GraphQL API — manage runs, assets, schedules, sensors, and backfills from any MCP client
Project description
Dagster MCP
An MCP server that gives AI agents full visibility and control over your Dagster instance — like an SRE for your data pipelines.
Works with any MCP client: Claude Code, Claude Desktop, Cursor, and more.
Why this exists
Data pipelines break at 3 AM. Schedules silently stop firing. Assets go stale. Instead of waking up to a dashboard full of red, give your AI agent the tools to monitor, diagnose, and fix your Dagster instance autonomously.
Agent: Checking instance health...
get_instance_status() -> healthy: false, daemon "SCHEDULER" unhealthy
Agent: Scheduler daemon is down. Let me check recent failures...
get_runs(statuses=["FAILURE"], limit=5) -> 3 failed runs in the last hour
Agent: Diagnosing the most recent failure...
get_run_failure_summary("run_abc123") ->
failed_steps: ["transform_orders"]
root_cause: "NullPointerError: column 'price' is null"
suggestions: ["Single step failed — consider re-running from failure"]
Agent: Re-launching the failed job...
launch_job("etl_pipeline", "my_project") -> run_id: "run_def456", status: STARTED
Agent: One sensor keeps firing on bad data. Checking its ticks...
get_tick_history("orders_sensor", "SENSOR") -> 12 consecutive FAILURE ticks
Agent: Stopping it until the upstream fix lands...
stop_sensor("orders_sensor") -> status: STOPPED
What it does
27 tools across 6 categories, designed for autonomous DataOps workflows:
| Category | Tools | What an agent can do |
|---|---|---|
| Runs | get_runs get_run_status get_run_logs get_run_stats get_run_failure_summary |
Find failures, diagnose root causes, inspect logs and step timing |
| Assets | search_assets resolve_asset_selection get_asset_details get_recent_materializations get_asset_health |
Discover assets, preview lineage selections, check freshness, detect stale data |
| Jobs | list_jobs |
Inventory all jobs across code locations |
| Schedules & Sensors | list_schedules list_sensors get_tick_history |
Detect silent failures, missed ticks, sensor errors |
| Instance | get_instance_status list_code_locations list_backfills |
Global health check, daemon status, code location errors |
| Actions | materialize_assets backfill_assets launch_job launch_job_with_partitions terminate_run start_schedule stop_schedule start_sensor stop_sensor reload_code_location |
Materialize concrete assets with config, backfill partitions, launch jobs, stop stuck runs, start or stop schedules and sensors, reload after deploy |
Actions are opt-in: set
DAGSTER_READ_ONLY=falseto enable write operations.
Quick start
Prerequisites
Install
The package is published on PyPI.
Option A — run directly with uvx (no install needed):
uvx dagster-mcp
Option B — install with pip:
pip install dagster-mcp
Option C — clone and run:
git clone https://github.com/fabdendev/dagster-mcp.git
cd dagster-mcp
uv sync
Configure
Single environment
| Variable | Description | Default |
|---|---|---|
DAGSTER_URL |
Base URL of your Dagster instance | http://localhost:3000 |
DAGSTER_API_TOKEN |
Dagster Cloud API token (leave empty for self-hosted) | (empty) |
DAGSTER_EXTRA_HEADERS |
JSON object of additional request headers sent to Dagster GraphQL | (empty) |
DAGSTER_READ_ONLY |
When true, only read tools are exposed (no launch/terminate/reload, no schedule or sensor start/stop) |
true |
Self-hosted:
export DAGSTER_URL=http://localhost:3000
Dagster Cloud:
export DAGSTER_URL=https://myorg.dagster.cloud/prod
export DAGSTER_API_TOKEN=your-dagster-cloud-user-token
Custom auth / proxy headers:
export DAGSTER_EXTRA_HEADERS='{"Authorization":"Bearer your-token","X-My-Header":"value"}'
Multiple environments
Use DAGSTER_ENVS to configure several Dagster instances in one server. Every tool then accepts an optional env parameter so the LLM can target the right instance.
| Variable | Description | Default |
|---|---|---|
DAGSTER_ENVS |
JSON object mapping env names to {url, token?, extra_headers?} configs |
(empty) |
DAGSTER_DEFAULT_ENV |
Env name to use when env is not passed to a tool |
(empty) |
export DAGSTER_ENVS='{
"prod": {"url": "https://myorg.dagster.cloud/prod", "token": "prod-token"},
"staging": {"url": "https://myorg.dagster.cloud/staging", "token": "stg-token"},
"dev": {"url": "http://localhost:3000"}
}'
export DAGSTER_DEFAULT_ENV=prod
When DAGSTER_ENVS is set, DAGSTER_URL / DAGSTER_API_TOKEN / DAGSTER_EXTRA_HEADERS are ignored. If only one env is defined, it is used automatically even without DAGSTER_DEFAULT_ENV.
Add to your MCP client
Claude Code
Add to ~/.claude/settings.json:
Single env:
{
"mcpServers": {
"dagster": {
"command": "uvx",
"args": ["dagster-mcp"],
"env": {
"DAGSTER_URL": "http://localhost:3000"
}
}
}
}
Multiple envs:
{
"mcpServers": {
"dagster": {
"command": "uvx",
"args": ["dagster-mcp"],
"env": {
"DAGSTER_ENVS": "{\"prod\":{\"url\":\"https://myorg.dagster.cloud/prod\",\"token\":\"prod-token\"},\"dev\":{\"url\":\"http://localhost:3000\"}}",
"DAGSTER_DEFAULT_ENV": "prod"
}
}
}
}
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"dagster": {
"command": "uvx",
"args": ["dagster-mcp"],
"env": {
"DAGSTER_URL": "http://localhost:3000"
}
}
}
}
From a local clone
{
"mcpServers": {
"dagster": {
"command": "uv",
"args": ["run", "--directory", "/path/to/dagster-mcp", "dagster-mcp"],
"env": {
"DAGSTER_URL": "http://localhost:3000"
}
}
}
}
Tool reference
Runs
| Tool | Description |
|---|---|
get_runs |
List recent runs, filter by job name and/or status |
get_run_status |
Get status, config, tags, and run lineage (re-execution chain via rootRunId/parentRunId) |
get_run_logs |
Get structured log events with pagination and optional level filtering (ERROR, WARNING, INFO); EngineEvent events include metadataEntries |
get_run_stats |
Get per-step execution stats: timing, materializations, expectation results |
get_run_failure_summary |
Consolidated failure diagnosis — failed steps, root cause error, step durations, and suggestions in one call |
Assets
| Tool | Description |
|---|---|
search_assets |
Discover assets by key prefix or group name |
resolve_asset_selection |
Resolve key/group/tag/kind/owner predicates, wildcards, boolean logic, roots/sinks, and lineage traversal into concrete asset keys without launching anything |
get_asset_details |
Get description, upstream/downstream dependencies, partitions, latest materialization |
get_recent_materializations |
Get materialization history with metadata for an asset |
get_asset_health |
Consolidated health view — staleness, freshness policy, last run status (works with single asset or entire group) |
Two-step asset workflow
Start by resolving and reviewing a selection expression:
resolve_asset_selection(
asset_selection="group:analytics and (kind:dbt or key:*benchmark)"
)
→ {
"asset_keys": [
"warehouse/analytics/orders",
"warehouse/analytics/reranker_benchmark"
],
"assets": [...]
}
For concrete, unpartitioned assets, pass the returned keys to
materialize_assets with any required launch config and tags:
materialize_assets(
asset_keys=[
"warehouse/analytics/orders",
"warehouse/analytics/reranker_benchmark"
],
run_config={"ops": {"benchmark": {"config": {"limit": 1000}}}},
tags={"triggered_by": "agent"}
)
For partitioned assets, pass the same resolved keys to backfill_assets
instead:
backfill_assets(
asset_keys=["warehouse/analytics/daily_orders"],
partition_start="2026-07-01",
partition_end="2026-07-07",
run_config={"resources": {"warehouse": {"config": {"pool": "benchmark"}}}}
)
resolve_asset_selection is available in both read-only and read-write modes.
It returns external, observable, non-executable, and partitioned matches so the
caller can inspect the complete result. The write tools re-fetch current asset
definitions before execution. resolve_asset_selection and materialize_assets
require Dagster 1.9+.
Jobs, Schedules & Sensors
| Tool | Description |
|---|---|
list_jobs |
List all jobs across all code locations (use to find names for launch_job) |
list_schedules |
List schedules with status (RUNNING/STOPPED), cron, target job, next tick |
list_sensors |
List sensors with status and target jobs |
get_tick_history |
Tick-by-tick history for a schedule or sensor — essential for detecting silent failures. Accepts optional repository_name / location_name to disambiguate a name shared by several code locations |
Instance & Code Locations
| Tool | Description |
|---|---|
get_instance_status |
Start here — global health: daemon status, queued run count, code location errors |
list_code_locations |
List all code locations and their load status |
list_backfills |
List recent backfills with status and partition progress |
Write Operations
| Tool | Description |
|---|---|
materialize_assets |
Launch concrete, unpartitioned asset keys with run config and tags; infers one compatible repository/job, includes compatible checks, and expands required non-subsettable multi-asset neighbors |
backfill_assets |
Launch a partition backfill by asset selection with optional run config; respects each asset's BackfillPolicy server-side |
launch_job |
Launch a named job; asset_keys remains supported for compatibility and is sent through GraphQL assetSelection, but the two-step asset workflow is preferred |
launch_job_with_partitions |
Launch a partitioned job for one or more partition keys; creates a backfill (supports from_failure to retry only failed steps) |
start_schedule |
Start (enable) a schedule so it launches runs on its cron |
stop_schedule |
Stop (disable) a schedule — persists across restarts; does not terminate in-flight runs |
start_sensor |
Start (enable) a sensor so it resumes evaluating |
stop_sensor |
Stop (disable) a sensor — the fix for a runaway or erroring sensor found via get_tick_history |
Schedule/sensor names are unique only within a repository. If the same name exists in several code locations, the start/stop tools refuse to act and list the candidates; pass
repository_name/location_nameto disambiguate. Successful calls echo the resolvedrepositoryandlocation. |terminate_run| Stop a stuck or runaway run | |reload_code_location| Reload a code location after deploy |
Write tools require
DAGSTER_READ_ONLY=false(default istrue).
How it differs from the official Dagster MCP
| dagster-mcp (this project) | dg[mcp] (official) | |
|---|---|---|
| Purpose | Monitor and operate a running instance | Write Dagster code and scaffold components |
| When | Operations time | Development time |
| What it does | Inspect runs, read logs, check assets, launch jobs | Generate definitions, use dg CLI, build pipelines |
They serve different purposes and work well together.
Compatibility
The monitoring and existing action tools are tested with Dagster 1.6+.
resolve_asset_selection and materialize_assets require Dagster 1.9+ and
verify the required GraphQL capabilities before querying or launching. The
RunsFilter field name (jobName vs pipelineName) is auto-detected via schema
introspection. Configured asset backfills also feature-detect
LaunchBackfillParams.runConfigData and return a clear compatibility error when
an older schema does not expose it. Schedule and sensor start/stop work on
Dagster 1.6+: the stop mutations are sent with the originId/selectorId
argument pair sourced from InstigationState.id/selectorId, which modern
Dagster re-parses as a compound id and older versions accept directly, so no
version branch is needed. The mutations select error messages via the
... on Error interface fragment rather than per-type fragments, because
ScheduleNotFoundError only joined ScheduleMutationResult in Dagster 1.9 and
spreading it on 1.6-1.8 would fail document validation.
Development
uv sync --extra dev
uv run ruff check dagster_mcp/ # lint
uv run pytest # run the test suite
uv run python -m dagster_mcp # start server locally
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dagster_mcp-0.8.0.tar.gz.
File metadata
- Download URL: dagster_mcp-0.8.0.tar.gz
- Upload date:
- Size: 105.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
524d4eea35e5d4503ea4c4e9857fac67aaea675d269b6875d24d0dda28f8eef6
|
|
| MD5 |
77ae310ec63ad9025b7222af262be4e7
|
|
| BLAKE2b-256 |
51d5a6de36fa947d47def8633fc6a372e8b56b31aa847f2a89e90e5153bdbae7
|
Provenance
The following attestation bundles were made for dagster_mcp-0.8.0.tar.gz:
Publisher:
release.yml on fabdendev/dagster-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dagster_mcp-0.8.0.tar.gz -
Subject digest:
524d4eea35e5d4503ea4c4e9857fac67aaea675d269b6875d24d0dda28f8eef6 - Sigstore transparency entry: 2257384156
- Sigstore integration time:
-
Permalink:
fabdendev/dagster-mcp@18566ccefb510f86a323f786d0140248c17cea9e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/fabdendev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@18566ccefb510f86a323f786d0140248c17cea9e -
Trigger Event:
push
-
Statement type:
File details
Details for the file dagster_mcp-0.8.0-py3-none-any.whl.
File metadata
- Download URL: dagster_mcp-0.8.0-py3-none-any.whl
- Upload date:
- Size: 33.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bbe8baf61f3a5a5f4b74dc536a6395408cf0a250fed4e7874397b3e3478fed9b
|
|
| MD5 |
a7acee13f64e595a984b1fc53e7535e7
|
|
| BLAKE2b-256 |
07b15ec1904c51024a7add050db31ddae11c249a122e6370c403d87518717cf3
|
Provenance
The following attestation bundles were made for dagster_mcp-0.8.0-py3-none-any.whl:
Publisher:
release.yml on fabdendev/dagster-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dagster_mcp-0.8.0-py3-none-any.whl -
Subject digest:
bbe8baf61f3a5a5f4b74dc536a6395408cf0a250fed4e7874397b3e3478fed9b - Sigstore transparency entry: 2257384160
- Sigstore integration time:
-
Permalink:
fabdendev/dagster-mcp@18566ccefb510f86a323f786d0140248c17cea9e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/fabdendev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@18566ccefb510f86a323f786d0140248c17cea9e -
Trigger Event:
push
-
Statement type: