Skip to content
Open
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
32 changes: 32 additions & 0 deletions .github/workflows/basic-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ on: # yamllint disable-line rule:truthy
description: "Whether to run scripts tests (true/false)"
required: true
type: string
run-mcp-server-tests:
description: "Whether to run dev MCP server tests (true/false)"
required: true
type: string
basic-checks-only:
description: "Whether to run only basic checks (true/false)"
required: true
Expand Down Expand Up @@ -97,6 +101,34 @@ jobs:
- name: "Run unit tests"
run: uv tool run --from apache-airflow-breeze pytest -n auto --color=yes
working-directory: ./dev/breeze/
tests-mcp-server:
timeout-minutes: 10
name: Dev MCP server tests
Comment thread
shahar1 marked this conversation as resolved.
runs-on: ${{ fromJSON(inputs.runners) }}
if: inputs.run-mcp-server-tests == 'true'
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 1
persist-credentials: false
- name: "Install uv"
# Extract uv version from uv.lock. The format is stable: the line
# immediately after `name = "uv"` is `version = "<X.Y.Z>"`.
run: |
UV_VERSION=$(sed -n '/^name = "uv"$/{n;s/^version = "\(.*\)"$/\1/p;}' uv.lock)
if [[ -z "${UV_VERSION}" ]]; then
echo "Failed to extract uv version from uv.lock" >&2
exit 1
fi
echo "Installing uv==${UV_VERSION}"
pip install "uv==${UV_VERSION}"
# Standalone uv project (its own uv.lock), like dev/breeze -- resolve and run in isolation.
# AIRFLOW_MCP_LIVE_TESTS is unset, so the live-Breeze tests skip; the manual LLM-client
# integration script under tests/manual/ is not collected by pytest.
- name: "Run dev MCP server tests"
run: uv run --project . pytest --color=yes
working-directory: ./dev/mcp_server/
run-breeze-integration-tests:
timeout-minutes: 120
name: Breeze integration tests
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ci-amd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ jobs:
run-task-sdk-integration-tests: ${{ steps.selective-checks.outputs.run-task-sdk-integration-tests }}
run-breeze-integration-tests: ${{ steps.selective-checks.outputs.run-breeze-integration-tests }}
run-scripts-tests: ${{ steps.selective-checks.outputs.run-scripts-tests }}
run-mcp-server-tests: ${{ steps.selective-checks.outputs.run-mcp-server-tests }}
runner-type: '["ubuntu-22.04"]'
run-ui-tests: ${{ steps.selective-checks.outputs.run-ui-tests }}
run-ui-e2e-tests: ${{ steps.selective-checks.outputs.run-ui-e2e-tests }}
Expand Down Expand Up @@ -254,6 +255,7 @@ jobs:
canary-run: ${{needs.build-info.outputs.canary-run}}
run-breeze-integration-tests: ${{needs.build-info.outputs.run-breeze-integration-tests}}
run-scripts-tests: ${{needs.build-info.outputs.run-scripts-tests}}
run-mcp-server-tests: ${{needs.build-info.outputs.run-mcp-server-tests}}
latest-versions-only: ${{needs.build-info.outputs.latest-versions-only}}
use-uv: ${{needs.build-info.outputs.use-uv}}
platform: ${{ needs.build-info.outputs.platform }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ci-arm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ jobs:
run-task-sdk-integration-tests: ${{ steps.selective-checks.outputs.run-task-sdk-integration-tests }}
run-breeze-integration-tests: ${{ steps.selective-checks.outputs.run-breeze-integration-tests }}
run-scripts-tests: ${{ steps.selective-checks.outputs.run-scripts-tests }}
run-mcp-server-tests: ${{ steps.selective-checks.outputs.run-mcp-server-tests }}
runner-type: '["ubuntu-22.04-arm"]'
run-ui-tests: ${{ steps.selective-checks.outputs.run-ui-tests }}
run-ui-e2e-tests: ${{ steps.selective-checks.outputs.run-ui-e2e-tests }}
Expand Down Expand Up @@ -243,6 +244,7 @@ jobs:
canary-run: ${{needs.build-info.outputs.canary-run}}
run-breeze-integration-tests: ${{needs.build-info.outputs.run-breeze-integration-tests}}
run-scripts-tests: ${{needs.build-info.outputs.run-scripts-tests}}
run-mcp-server-tests: ${{needs.build-info.outputs.run-mcp-server-tests}}
latest-versions-only: ${{needs.build-info.outputs.latest-versions-only}}
use-uv: ${{needs.build-info.outputs.use-uv}}
platform: ${{ needs.build-info.outputs.platform }}
Expand Down
29 changes: 29 additions & 0 deletions dev/breeze/doc/03_developer_tasks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,35 @@ These are all available flags of ``start-airflow`` command:
:width: 100%
:alt: Breeze start-airflow

MCP server for AI-assisted debugging
-------------------------------------

Breeze can start an internal, development-only MCP (Model Context Protocol) server alongside
the other Airflow components. It exposes the running breeze Airflow instance's public REST API
as MCP tools, so any MCP-capable coding agent (Claude Code, Cursor, or any other client of the
vendor-neutral MCP protocol) can inspect and help debug your local Dags, Dag runs, task logs,
and import errors without you copy-pasting API responses by hand. It is internal tooling only -
it is never shipped to users or included in any released distribution.

Start it with:

.. code-block:: bash

breeze start-airflow --mcp-server

Once running, the server is reachable from the host at ``http://localhost:28081/mcp``. Point any
MCP client that supports streamable HTTP transport at that URL.

The server is read-only unless ``AIRFLOW_MCP_ALLOW_WRITES`` is set. ``DELETE`` calls are gated more
strictly still, behind a separate ``AIRFLOW_MCP_ALLOW_DELETES`` flag that stays off even when writes
are enabled, since deletions are irreversible. The breeze deployment sets ``AIRFLOW_MCP_ALLOW_WRITES=true``
by default (the environment is disposable) but leaves deletions disabled - start breeze with
``AIRFLOW_MCP_ALLOW_WRITES=false breeze start-airflow --mcp-server`` for a strictly read-only server,
or set ``AIRFLOW_MCP_ALLOW_DELETES=true`` if you deliberately need deletions. See
`dev/mcp_server/README.md <../../mcp_server/README.md>`__ for host-side
``stdio`` usage (your MCP client spawns the server as a local subprocess, no breeze flag needed),
the full tool list, and the complete safety model.

Running External System Integrations with Breeze
------------------------------------------------

Expand Down
Loading