mcp-dagster
This MCP server exposes read-only Dagster inspection capabilities through six tools.
Overview: repository/job list, last 10 runs, backfills, and active schedules.
Assets: list assets with code version, last materialization, and partition count; fetch one asset’s state/metadata by key.
Runs: list runs filtered by job/status; fetch run detail by
run_id(status, tags, metadata, step states).Automation: list sensors and schedules with their state.
Constraints: the provided schema does not expose write/materialization, raw GraphQL, backfill, workspace, or examples tools from the README.
Provides tools for querying a Dagster instance's GraphQL 1.x API, including specialized tools and raw read-only GraphQL queries for exploring workspaces, assets, partitions, lineage, runs, automations, and backfills.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-dagster show me the latest dagster runs and any failed assets"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-dagster
Un MCP pour interroger l'API GraphQL 1.x d'une instance Dagster : workspace/code locations, assets, états de partitions, lineage, runs, automatisations (schedules/sensors), backfills.
Design V2 : le serveur privilégie la latitude de l'agent. Les
outils spécialisés couvrent les questions courantes ; dagster_examples
fournit des requêtes GraphQL modèles documentées que l'agent peut
adapter, combiner et lancer via dagster_raw_query (accès au schéma
complet). Toutes les requêtes embarquées sont validées contre le vrai
schéma 1.12.1 (fixture tests/schema_1_12_1.graphql).
Lecture d'abord : en mode read_only (défaut), aucune opération
d'écriture n'est autorisée — y compris une mutation transmise via
dagster_raw_query. La seule écriture fournie est dagster_materialize,
derrière read_only: false ET une confirmation explicite
(read_only=false au niveau du tool).
Installation
python -m venv .venv
.venv/bin/pip install . # ou : pip install ".[dev]"Le point d'entrée s'appelle mcp-dagster (stdio, compatible n'importe quel
client MCP : Claude, Hermes, …).
Related MCP server: graphql-introspection-mcp
Configuration
Deux façons, la dernière gagnant :
Fichier YAML — par défaut
./config.yaml, puis~/.config/mcp-dagster/config.yaml, sinon le chemin de l'envDAGSTER_MCP_CONFIG:base_url: "https://dagster.example.org" api_token: "" # Bearer ; ne pas mettre en clair (voir env) forward_header: "" # mode relay du jeton utilisateur (voir plus bas) graphql_url: "" # URL absolue du point d'entrée GraphQL (défaut : <base_url>/graphql) timeout: 30 read_only: true # défaut : tout write GraphQL refusé extra_headers: {}Variables d'env (recommandées pour le token) :
Variable
Champ
DAGSTER_MCP_CONFIGchemin du fichier YAML
DAGSTER_MCP_BASE_URLbase_urlDAGSTER_MCP_API_TOKENapi_tokenDAGSTER_MCP_FORWARD_HEADERforward_headerDAGSTER_MCP_GRAPHQL_URLgraphql_url(URL absolue du point d'entrée GraphQL)DAGSTER_MCP_TIMEOUTtimeoutDAGSTER_MCP_READ_ONLYread_only(0/1,true/false)DAGSTER_MCP_PORTport HTTP du serveur conteneur (défaut
8080)
L'API est contactée par défaut sur <base_url>/graphql (layout standard d'une
instance Dagster, l'UI est sur /). Si votre instance expose le point
d'entrée ailleurs, définissez graphql_url (YAML) ou DAGSTER_MCP_GRAPHQL_URL
(une URL absolue, ex. https://dagster.example.org/api).
Authentification derrière oauth2-proxy : si l'instance passe par oauth2-proxy + un IdP (Keycloak, …), il faut un token que le proxy accepte. Si le client OIDC côté proxy est confidential, le password grant headless échoue sans son
client_secret— dans ce cas un token provisionné (Vault, variable CI, ou un client OAuth dédié public) est la voie la plus simple. Vérifiez la nature du client OIDC de votre proxy avant de brancher un token.
Relay du jeton utilisateur (forward_header) — mode HTTP partagé
En mode conteneur streamable-HTTP stateless, le serveur est partagé par
tous les utilisateurs via un seul process. Un api_token statique figé au
démarrage donnerait à tout le monde les mêmes droits Dagster, même pour
celui que l'oauth2-proxy a déjà filtré en amont. Le serveur MCP ne doit jamais
élargir les droits d'un utilisateur.
Solution : le serveur relaie, tel quel, le jeton de la requête MCP entrante au lieu d'utiliser un token figé.
# Mode relay (à la place de api_token)
base_url: "https://dagster.example.org"
forward_header: "Authorization" # nom du header à relayer vers Dagster
# api_token doit rester vide / absentComportement :
Chaque requête MCP entrante doit porter le header configuré (ex.
Authorization: Bearer <jeton de l'utilisateur>).Sa valeur est relayée telle quelle comme
Authorizationsur l'appel GraphQL sortant (vers le point d'entrée configuré, par défaut<base_url>/graphql).Si le header est absent ou vide : l'appel échoue explicitement côté MCP (message d'erreur clair). Aucun repli sur
api_token.Si
api_tokenETforward_headersont définis : erreur de démarrage (mutuellement exclusifs) — ne configurer qu'un des deux.Le mode
stdio(usage local, un seul utilisateur) gardeapi_tokentel quel ;forward_headerest conçu pour le mode HTTP partagé.
Exemple consommateur côté client MCP HTTP (pattern générique, sans nom de produit) :
# Config du client MCP HTTP qui consomme le serveur en mode partagé
mcpServers:
dagster:
url: "http://localhost:8080/mcp"
headers:
# Le client (ou le reverse proxy en amont) doit poser le jeton
# de l'utilisateur courant dans le header nommé par forward_header.
Authorization: "Bearer {{ current_user_token }}"En pratique, c'est l'infrastructure en amont (oauth2-proxy, load balancer, client MCP) qui injecte le jeton de l'utilisateur courant dans ce header — pas le LLM. Le serveur n'y touche pas : il le relaye tel quel.
Outils (V2 — API Dagster 1.x)
Lecture :
Outil | Description |
| locations + repositories, 10 derniers runs en erreur, backfills récents — point de départ |
| état détaillé des code locations (chargement, source de définitions, métadonnées) |
| assets du repository : clé, groupe, jobs, stockage, partitions |
| assets paginés (tous repos), filtrables par préfixe de clé |
| état complet d'un asset : partitions, fraîcheur, ressources, lineage amont/aval, dernières matérialisations |
| runs filtrables par job et/ou statut(s) |
| détail d'un run : tags, config, stats par step, 60 premiers événements (logs, échecs, métadonnées de matérialisation) |
| schedules + sensors : actif/désactivé, cron, prochain tick simulé, 5 derniers ticks |
| backfills en cours/terminés et leur progression par partition |
| jobs/pipelines du repository + partition sets |
Latitude agent :
Outil | Description |
| requêtes GraphQL modèles documentées (erreurs récentes, partitions du mois, queue, automatisations, locations, lineage, ressources↔assets, métadonnées de run) — à adapter puis lancer |
| requête GraphQL arbitraire lecture seule en mode |
Écriture (read-write uniquement) :
Outil | Description |
| matérialise des assets (backfill) — verrou serveur |
Si l'instance expose plusieurs repositories, les outils qui ciblent un
repository acceptent location/repository (les valeurs sont visibles via
dagster_overview) ; sinon le premier repository accessible est utilisé.
Exemple de déclaration (client MCP)
{
"mcpServers": {
"dagster": {
"command": "/chemin/.venv/bin/mcp-dagster",
"env": {
"DAGSTER_MCP_BASE_URL": "https://dagster.example.org",
"DAGSTER_MCP_API_TOKEN": "<token>",
"DAGSTER_MCP_READ_ONLY": "1"
}
}
}
}Image conteneur
Réseau / header Host. Le port du SDK mcp 1.x vers FastMCP 3.x a
supprimé à la racine l'ancienne protection anti-DNS-rebinding (contrôle du
header Host) qui provoquait des 421 Misdirected Request derrière un
réseau de conteneurs (le client envoie Host: <conteneur>:8080, pas un
loopback). Le SDK 3.x n'applique aucun contrôle de Host par défaut — plus
aucune configuration nécessaire ; un test de bout en bout le garantit
(tests/test_http_host.py, Host: mcp-dagster-ro:8080). L'authentification
réelle reste le relay du jeton utilisateur (voir ci-dessus).
Le conteneur expose le serveur en streamable-HTTP stateless sur le port
DAGSTER_MCP_PORT (défaut 8080) :
python -m mcp_dagsterConstruire et lancer :
podman build -t mcp-dagster:local -f Containerfile .
podman run --rm -p 8080:8080 \
-e DAGSTER_MCP_BASE_URL=https://dagster.example.org \
-e DAGSTER_MCP_API_TOKEN=*** \
-e DAGSTER_MCP_READ_ONLY=true \
mcp-dagster:local
# endpoint MCP : http://localhost:8080/mcpExtrait de compose pour LibreChat (serveur MCP HTTP) :
services:
mcp-dagster:
image: ghcr.io/votre-org/mcp-dagster:latest
environment:
- DAGSTER_MCP_BASE_URL=https://dagster.example.org
- DAGSTER_MCP_API_TOKEN=*** # via Vault, jamais en clair
- DAGSTER_MCP_READ_ONLY=true
restart: unless-stoppedL'image est publiée sur GHCR par la CI GitHub Actions (voir
.github/workflows/ci.yml) : tag immuable par commit, plus latest sur la
branche par défaut et par tag.
Tests
.venv/bin/python -m pytest tests/ -qTous les tests sont hors-réseau (client httpx mocké). Les 19 requêtes
embarquées (outils + exemples) sont validées dans la suite contre le vrai
schéma Dagster 1.12.1 (fixture tests/schema_1_12_1.graphql, généré via
create_schema() de dagster-graphql) : tout dérive de schéma échoue les
tests.
Convention de versionnage
La version du MCP = la version de Dagster visée (ex. tag v1.12.1 du
repo ↔ webserver Dagster 1.12.1). Quand le support d'une autre version de
Dagster sera ajouté (nouvelle fixture de schéma + validation), le tag
suivant reflète la version visée.
Limites connues / suite
Les requêtes sont calées sur le schéma Dagster 1.12.1 ; sur des versions très différentes du webserver, un champ peut avoir bougé —
dagster_raw_query(et les erreurs GraphQL remontées) restent le plan B.dagster_materialize(backfill d'assets) est le seul outil d'écriture ; les autres écritures (terminer un run, recharger un repository, …) passent pardagster_raw_queryen read-write, à l'initiative de l'opérateur.Pas encore de streaming des logs de run en continu (les 60 premiers événements sont retournés par
dagster_run_detail).
Licence
GPL-3.0-or-later — voir LICENSE.
Available Tools
6 toolsdagster_asset_stateC
État et métadonnées d'un asset (key = chemin, ex. "ch.dataset" ou "ch/dataset" ; le « . » est normalisé en « / »).
Inputs: key (required). Returns: result
dagster_list_assetsB
Liste des assets Dagster avec leur code version, dernière matérialisation et nombre de partitions.
Inputs: page_size. Returns: result
dagster_list_runsB
Liste des runs (optionnel : filtre par job et/ou statut, ex. SUCCESS, FAILURE, RUNNING, CANCELLED).
Inputs: status, job_name, page_size. Returns: result
dagster_overviewB
Vue d'ensemble de l'instance Dagster : nom du dépôt, liste des jobs, 10 derniers runs, backfills et schedules actifs.
Inputs: page_size. Returns: result
dagster_run_detailB
Détail d'un run Dagster (id du run) : statut, job, tags, métadonnées de run et état de chaque step.
Inputs: run_id (required). Returns: result
dagster_sensors_schedulesB
Sensors et schedules de l'instance avec leur état.
Inputs: no named parameters. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 6 tools
Each tool targets a distinct resource: instance summary, asset list, single asset state, run list, single run detail, and sensors/schedules. The only soft overlap is dagster_overview, which summarizes runs and schedules that dagster_list_runs and dagster_sensors_schedules also expose, but the descriptions make the summary-vs-detail distinction clear enough.
All tools share the dagster_ prefix and snake_case, giving a predictable namespace. Most follow a verb_noun shape (list_assets, list_runs, run_detail, asset_state), with dagster_overview and dagster_sensors_schedules being minor deviations but still readable.
Six tools is well-scoped for a Dagster observability surface, covering summary, assets, runs, and schedules without redundancy. Every tool earns its place and nothing feels like filler.
The surface is read-only: there is no way to launch or re-run a job, trigger a backfill (despite backfills being mentioned in the overview), or materialize an asset, and no run logs access. These are notable gaps for an agent trying to act on Dagster, though inspection workflows are well covered.
Maintenance
Related MCP Connectors
Run read-only GraphQL queries and list documents and media assets in Caisy.
Query your OpsLevel internal developer portal: catalog, maturity data, and tech docs.
Query Honeycomb observability data: traces, events, metrics, SLOs, triggers, and boards.
Provides read access to your GKE and Kubernetes resources.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables read-only interaction with Hasura GraphQL APIs, including table exploration, data preview, and schema introspection.14 npmMIT
- AlicenseAqualityDmaintenanceProvides comprehensive GraphQL introspection, filtering, and query/mutation execution with safety controls. Enables AI agents to explore and interact with GraphQL APIs through natural language.714 npm1MIT
- AlicenseBqualityDmaintenanceExposes any GraphQL API as a single tool for executing queries and mutations with authentication support.1MIT
- FlicenseNot gradedqualityDmaintenanceEnables running read-only SQL queries and exploring DuckDB databases through MCP tools like listing tables, describing schemas, and fetching paginated data.-