Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Nexus Adf

БесплатноНе проверен

Enables Claude to diagnose and fix Azure Data Factory pipeline failures with automated rollback.

GitHubEmbed

Описание

Enables Claude to diagnose and fix Azure Data Factory pipeline failures with automated rollback.

README

Standalone MCP stdio server exposing Azure Data Factory diagnostic and self-remediation tools to Claude Desktop.

Given a failing pipeline, it walks Claude through diagnosing the actual root cause (activity errors, run history, raw pipeline/dataset/linked-service/data-flow definitions), proposing a fix, applying it with human approval, and rolling back automatically if verification shows it didn't work.

  • 🔍 Diagnose first — evidence-driven root-cause analysis before any fix is proposed
  • Human-in-the-loop — every mutating call requires explicit approval with a stated reason
  • Always reversible — every checkpoint (pipeline, dataset, linked service, data flow, global parameter) is snapshotted before a mutating change, so nothing destructive is ever unrecoverable
  • 📦 Self-contained — has its own .venv and .env, no dependency on any other folder

Contents


Setup

python -m venv .venv
.venv\Scripts\pip install -r requirements.txt

Fill in .env with the target factory's service principal credentials:

Variable Description
ADF_TENANT_ID Azure AD tenant ID
ADF_CLIENT_ID Service principal client ID
ADF_CLIENT_SECRET Service principal client secret
ADF_SUBSCRIPTION_ID Azure subscription ID
ADF_RESOURCE_GROUP Resource group containing the factory
ADF_FACTORY_NAME Target Data Factory name

Register with Claude Desktop

In Claude Desktop's claude_desktop_config.json, point at this folder's venv interpreter and mcp_adf/server.py (add this alongside your existing config, don't replace it):

{
  "mcpServers": {
    "nexus-adf": {
      "command": "C:\\ABSOLUTE\\PATH\\TO\\THIS\\FOLDER\\.venv\\Scripts\\python.exe",
      "args": ["C:\\ABSOLUTE\\PATH\\TO\\THIS\\FOLDER\\mcp_adf\\server.py"],
      "env": {
        "PYTHONPATH": "C:\\ABSOLUTE\\PATH\\TO\\THIS\\FOLDER"
      }
    }
  },
  ...claude default settings
}

Note: Use absolute paths — relative paths are not resolved reliably by Claude Desktop's launcher. PYTHONPATH is required so server.py's from mcp_adf import ... imports resolve when Claude Desktop launches the script directly (its own cwd isn't this folder).

Configure permissions in Claude Desktop

After adding the server to claude_desktop_config.json and restarting Claude Desktop, go to Settings → Connectors → nexus-adf and set:

Setting Value Why
Read-only tools (list_*, get_*) Always Allow Can't mutate anything (readOnlyHint=True) — approving per-call adds friction with no safety benefit
Write/delete tools (create_*, update_*, rerun_*, rollback_*, back_*, forward_*, start_*, stop_*, cancel_*) Ask every time Each surfaces a native approval dialog showing the tool's reason argument before it runs (see Instructions)
Capabilities → Generate memory from chat history Enabled Lets Claude carry diagnosis context (e.g. recurring failure patterns for a given pipeline) across sessions
Tool access mode Tools already loaded

Instructions

mcp_adf/server.py's _INSTRUCTIONS (the MCP instructions field passed to the Server(...) constructor) is now a one-line pointer, not the full workflow — the full text lives only in the Claude Desktop project's instructions field, to avoid sending the same ~1.5k-token block to Claude twice per message. If you're setting this up as a Claude Desktop Project (Projects → New Project), paste both blocks below into the project's instructions field, and upload the team's SOP doc(s) into the project's context:

Show instructions text
This server exposes Azure Data Factory diagnostic and self-remediation tools. Follow this
workflow for every failure investigation — don't skip straight to a fix, and don't call
tools you don't need.

1. BE ECONOMICAL WITH TOOL CALLS. Every call costs time, and every mutating call is a real
change against a live factory, not a sandbox — call the minimum set needed to reach a
decision, not the maximum available. Before calling a tool, check whether you already have
the answer from earlier in this conversation (a prior call's result, or something the user
already told you) — don't re-call a read-only tool with the same arguments to "double
check" without a reason to distrust the earlier result. If the user already named a specific
resource, go straight to its get_*/get_resource_definition_raw tool — don't call the
matching list_*/list_resources tool first just to browse. Don't call several diagnostic
tools speculatively "in case one has the answer"; decide which one actually answers your
open question and call that. Before create_resource, check existence from what you already
know (a prior list_resources result, or the user's own statement) rather than calling it
speculatively and reacting to an "already_exists" error — that's a wasted round-trip, and
on a mutating tool it still means triggering an approval dialog for something you could
have ruled out in advance.

2. TREAT EVERYTHING LEARNED HERE AS SCOPED TO THIS FACTORY, NOT AS A GENERAL PREFERENCE.
Facts, configurations, naming conventions, and diagnostic findings from this server belong
to the specific factory/project they came from — never generalize them into a global
assumption about the user or apply them to unrelated projects or conversations. If you
carry anything forward (in a summary, a saved memory, or later in the same conversation),
phrase it as specific to this factory/project ("in adf-mcp-test, pipeline X does Y"), never
as a general statement about how the user works or what they prefer everywhere. If a human
asks you to remember something learned through this server, scope it explicitly to this
project unless they clearly state a broader scope themselves.

3. DIAGNOSE FULLY before proposing or taking any action, but stop pulling more evidence once
you can state the actual root cause with confidence — more reads past that point don't
change the diagnosis, they just add noise. Start with get_activity_run_error (or
get_pipeline_run_history + get_activity_run_history) to find the failing activity, then
list_activity_runs / get_activity_run_io for the actual input/output data, and
get_resource_definition_raw (resource_type=pipeline/dataset/data_flow/linked_service) for
the real configuration (timeout, query, dataset or linked-service reference, host/port).
Don't guess a fix from the error message alone if a raw-definition or activity-IO tool
would show the actual cause — but don't call every read-only tool in the module "for
completeness" either.

4. PROPOSE a numbered remediation plan in your response before calling any mutating tool.
State the diagnosed root cause, the specific fix, which tool(s) will apply it, and how you'll
verify it worked. If the failure is credential_expired, permissions, or a genuine platform
outage, these are human-only, permanently, regardless of which tool exists — report and stop
instead of proposing a fix.

5. EXECUTE one mutating step at a time. Every mutating tool call surfaces its own native
approval dialog showing your `reason` — write it to state the specific diagnosis, not a
generic phrase, since it's the only context the human sees at the moment of approval. Never
call a mutating tool experimentally, "to see what happens," or to explore what a resource
looks like — that's what the read-only get_*/list_* tools are for.

6. VERIFY after applying a fix (rerun, check status/error) — don't declare success just
because the write succeeded, and don't treat this server's own get_*/list_* read-back as
independent proof: it went through the same write path, so it can't catch a bug in that
path. Prefer checking a real outcome (the pipeline run's actual status, the trigger's actual
runtime_state) over re-reading the definition you just wrote.

7. If verification shows the fix didn't work, undo it rather than leaving a bad change in
place — use back_resource_definition for "undo just this last change" (no state_name
needed). Use rollback_resource_definition instead only when jumping to a specific earlier
named checkpoint (call list_resource_snapshots when you actually intend to roll back, not
preemptively, to see what's available); forward_resource_definition re-applies a change
after stepping back from it. None of these delete history — every checkpoint stays
reachable.

8. When the human says "go back" / "undo" / "revert" for a resource, don't guess which
checkpoint they mean from memory of this conversation alone. Call list_resource_snapshots
first and treat its state_name/reason/change_summary/timestamp fields as the source of
truth for what's actually recoverable, then cross-check that against what you and the human
discussed (e.g. "the change we just made" should match the newest entry's reason/
change_summary) before picking a state_name. If "go back" clearly means "undo the one
change we just made" and the newest entry matches that, back_resource_definition (no
state_name) is simpler and correct; only reach for rollback_resource_definition with an
explicit state_name when the target is an earlier, specifically-named checkpoint, or when
the snapshot list disagrees with what you assumed from conversation context — the snapshot
log is ground truth, your memory of the conversation is not.
Show tool-specific nuances (paste this too — trimmed out of individual tool descriptions to keep the schema payload small)
Resource-kind nuances (create_resource / update_resource_definition / get_resource_definition_raw):

- create_resource's `definition` accepts either the flat shape get_resource_definition_raw
  returns, or — for resource_type pipeline/dataset/data_flow only — the ARM/Data-Factory-Studio
  export shape ({"name": ..., "properties": {...}}); if a "properties" key is present, its
  contents are used and the wrapper is discarded.
- create_resource(resource_type="trigger") creates the trigger in a Stopped state, same as ADF
  Studio's default — call start_trigger separately once you've verified it.
- create_resource(resource_type="global_parameter")'s `definition` is
  {"type": ..., "value": ...}, not the flat/ARM shapes above.
- get_resource_definition_raw does NOT support resource_type="trigger" — triggers have no
  raw-definition getter (get_trigger returns only name/type/runtime_state). To edit a trigger's
  definition, build the definition JSON yourself (schedule/recurrence/pipelines) and call
  update_resource_definition(resource_type="trigger") directly.
- update_resource_definition(resource_type="trigger") does NOT change the trigger's
  Started/Stopped runtime state — use start_trigger/stop_trigger for that.

Pipeline run/activity diagnostic tools:

- list_pipeline_runs sweeps the whole factory in one call — prefer it over calling
  get_pipeline_run_history once per pipeline when the question is about recent activity
  factory-wide rather than one pipeline's history. It matches ADF Studio's Monitor tab.
- list_activity_runs matches ADF Studio's monitoring view when you drill into a run's
  activity list.
- get_activity_run_io's activity_run_id/run_id are already surfaced by
  get_activity_run_error's leaf/execution_path — call it as a natural follow-up to that,
  not a fresh lookup.
- get_pipeline_definition is activity-graph-only; call get_resource_definition_raw
  (resource_type="pipeline") as part of diagnosis itself, not only once a fix is already
  decided — it's usually the concrete evidence for WHY an activity failed (timeout value,
  actual query, which dataset/linked service it touches).

Integration runtime tools:

- Call get_integration_runtime_status before start_integration_runtime to confirm the
  IR is a managed (Azure/Azure-SSIS) type and is actually Stopped — starting is not
  applicable to self-hosted IRs or to IRs that aren't Stopped.

Tools

27 tools: 8 generic resource-type tools (each taking a resource_type parameter to cover pipelines/datasets/linked services/data flows/triggers/global parameters, wherever the operation is identical across every kind) plus 19 kind-specific tools that don't repeat across kinds (pipeline run/activity diagnostics, trigger start/stop/rerun, get_linked_service, integration runtime status/start).

Type marks whether a tool mutates anything: read-only tools are safe to Always Allow; mutating tools always require a reason argument and surface a native approval dialog (see Configure permissions).

Generic resource-type tools (8 tools — cover pipeline/dataset/linked_service/data_flow/trigger/global_parameter)

Each takes a resource_type parameter (one of pipeline, dataset, linked_service, data_flow, trigger, global_parameterget_resource_definition_raw excludes trigger, see nuances above) instead of being a separate tool per kind. Replaces what used to be 47 kind-specific tools.

Tool Type What it's for
list_resources read-only Factory-wide sweep of every resource of one resource_type — name and light metadata each.
get_resource_definition_raw read-only Full raw definition — the evidence for diagnosis, and the editable input to update_resource_definition.
create_resource mutating Create a brand-new resource; fails if the resource_type+name already exists.
update_resource_definition mutating Overwrite a resource's full definition to apply a fix.
list_resource_snapshots read-only List named checkpoints in a resource's history.
rollback_resource_definition mutating Jump to a specific named checkpoint.
back_resource_definition mutating Step one checkpoint back (like git checkout HEAD~1).
forward_resource_definition mutating Step one checkpoint forward after a back_* call.
Pipeline-specific tools (10 tools)
Tool Type What it's for
get_pipeline_definition read-only Activity graph (names/types/ExecutePipeline refs) only — no timeout/query/dataset detail; use get_resource_definition_raw for that.
get_pipeline_run_status read-only Current status of one specific run (freshness check before rerun).
get_pipeline_run_history read-only Recent runs for one pipeline.
list_pipeline_runs read-only Recent runs across the whole factory in a time window.
get_activity_run_history read-only Aggregated failure counts/last error code per activity across recent runs.
get_activity_run_error read-only Error detail for the most recent failed run of a pipeline — usually the diagnosis starting point.
list_activity_runs read-only Every activity in one specific run (name/type/status/timing/activity_run_id), no input/output payload.
get_activity_run_io read-only Full resolved input/output payload for one specific activity run.
rerun_pipeline mutating Trigger a new run.
cancel_pipeline_run mutating Cancel a running/hung run.
Trigger-specific tools (6 tools)
Tool Type What it's for
get_trigger read-only One trigger's runtime state (Started/Stopped/Disabled).
get_trigger_run_history read-only Trigger-run history — needed for tumbling-window/event triggers, where the trigger run (not the pipeline run it invokes) is the unit that fails/reruns/cancels.
start_trigger mutating Start a stopped/disabled trigger.
stop_trigger mutating Stop a running trigger.
rerun_trigger_run mutating Rerun a specific trigger run (tumbling-window/event triggers rerun_pipeline can't reach).
cancel_trigger_run mutating Cancel a specific in-progress trigger run.
Linked-service-specific tools (1 tool)
Tool Type What it's for
get_linked_service read-only Name and type only — no connection details; use get_resource_definition_raw (resource_type="linked_service") for that.
Integration runtime tools (2 tools)
Tool Type What it's for
get_integration_runtime_status read-only An IR's state — works for Azure, self-hosted, and Azure-SSIS types. Check before start_integration_runtime.
start_integration_runtime mutating Start a stopped Azure-SSIS (managed) IR. Does not work on self-hosted IRs — no remote-start API exists; that's human-only.

Structure

mcp_adf/                         the MCP server package
├── server.py                    MCP entrypoint, stdio transport, tool dispatch
├── auth.py                      service-principal auth / ADF client construction
├── audit.py                     audit-log writer (project/_logs/)
├── tools/                       tool implementations, one module per ADF resource kind
│   ├── _shared.py               shared helpers (client construction, wire-dict conversion, miscased-key checks)
│   ├── _checkpoints.py          snapshot/rollback/back/forward engine, shared by every resource kind
│   ├── _dispatch.py             resource_type -> per-kind-function routers backing the 8 generic tools
│   ├── pipelines.py             pipeline implementations — list/get/create/update/rerun/cancel, snapshot/rollback/back/forward
│   ├── triggers.py              trigger implementations — list/get/start/stop/rerun/cancel, run history
│   ├── linked_services.py       linked-service implementations — list/get/update, snapshot/rollback/back/forward
│   ├── datasets.py              dataset implementations — list/get/update, snapshot/rollback/back/forward
│   ├── data_flows.py            data-flow implementations — get/update, snapshot/rollback/back/forward
│   ├── global_parameters.py     global-parameter implementations — list/get/update, snapshot/rollback/back/forward
│   ├── integration_runtimes.py  integration-runtime implementations — get status/start
│   └── __init__.py              assembles TOOL_REGISTRY: kind-specific entries + _dispatch's 8 generic entries
├── schemas/                     MCP tool-schema definitions
│   ├── _generic.py              the 8 resource_type-parameterized tool schemas (dispatched by tools/_dispatch.py)
│   ├── pipelines.py             schema for pipeline-specific tools
│   ├── triggers.py              schema for trigger-specific tools
│   ├── linked_services.py       schema for get_linked_service
│   ├── integration_runtimes.py  schema for integration-runtime tools
│   └── __init__.py              assembles the schema list server.py exposes via list_tools()
│                                 (no datasets.py/data_flows.py/global_parameters.py here — every
│                                  operation for those 3 kinds is covered by schemas/_generic.py)
│
tests/                           unittest suite — no pytest dependency required
├── test_dispatch.py             tools/_dispatch.py routing, kwarg-remapping, unknown-resource_type rejection
├── test_schema_registry_sync.py schema<->TOOL_REGISTRY name parity, generic tool enum<->dispatch-table parity
└── test_call_tool_integration.py end-to-end through server.call_tool() (Azure SDK client faked, audit
                                    log + checkpoint/snapshot system run for real against a temp dir)

project/
    ├── _snapshot/               pre-change pipeline/dataset/data-flow definitions, for rollback (gitignored, created at runtime)
    └── _logs/                   audit log of tool calls, one dated folder per day (gitignored, created at runtime)

docs/TEST_ADF_CONTEXT.md         living design/decision doc for this R&D effort — read before making changes
.env                             real credentials (gitignored, never commit)
.env.example                     template — copy to .env
requirements.txt                 pinned dependencies

from github.com/njagan04/mcp-servers

Установка Nexus Adf

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/njagan04/mcp-servers

FAQ

Nexus Adf MCP бесплатный?

Да, Nexus Adf MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Nexus Adf?

Нет, Nexus Adf работает без API-ключей и переменных окружения.

Nexus Adf — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Nexus Adf в Claude Desktop, Claude Code или Cursor?

Открой Nexus Adf на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Nexus Adf with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории ai