Skip to main content

A durable DAG-based planner MCP utility for agent orchestration

Project description

dag-planner-mcp

A durable DAG-based task planner exposed as an MCP (Model Context Protocol) server. It lets AI orchestrators (Claude, ADK-based agents, etc.) break a goal into a dependency graph of tasks, execute them in parallel where possible, track state durably, and handle human-in-the-loop approval — all through a clean set of 22 MCP tools.


Table of Contents


Quick start with uvx

The fastest way to run the server is with uvx — no virtual environment or pip install needed:

uvx dag-planner-mcp

Pass arguments (e.g. HTTP transport) the same way:

uvx dag-planner-mcp --transport streamable-http --host 0.0.0.0 --port 8000

With an environment variable:

DATABASE_URL="sqlite:///dag_planner.db" uvx dag-planner-mcp

Claude Desktop — one-line config (uvx)

Open claude_desktop_config.json and add:

{
  "mcpServers": {
    "dag-planner-mcp": {
      "command": "uvx",
      "args": ["dag-planner-mcp"],
      "env": {
        "DATABASE_URL": "sqlite:////home/user/data/dag_planner.db"
      }
    }
  }
}

No installation step is required — uvx fetches and caches the package automatically on first run.


Install this skill

AI agents (Claude, Copilot, etc.) can pick up ready-made instructions for using this MCP server by installing the bundled skill:

npx skills add Shubhamnegi/dag-planner-mcp --skill use-mcp-tool

Or install directly from the skill path:

npx skills add https://github.com/Shubhamnegi/dag-planner-mcp/tree/main/skills/use-mcp-tool

What the skill provides

File Purpose
skills/use-mcp-tool/SKILL.md Core instructions — when/how to use the tool
skills/use-mcp-tool/references/setup.md Full installation and client integration guide
skills/use-mcp-tool/references/examples.md Runnable code examples (parallel tasks, HITL gates, checkpoints)
skills/use-mcp-tool/references/troubleshooting.md Common failure cases and fixes
skills/use-mcp-tool/scripts/smoke_test.py Quick sanity check — run after install
skills/use-mcp-tool/scripts/example_client.py Complete orchestrator example (stdio + HTTP)

Requirements

  • Python ≥ 3.11
  • DATABASE_URL environment variable (defaults to sqlite:///dag_planner.db)

Requirements

Dependency Version
Python ≥ 3.11
mcp[cli] ≥ 1.6.0
sqlalchemy ≥ 2.0
pydantic ≥ 2.0
jsonschema ≥ 4.0
aiosqlite ≥ 0.19

Optional (PostgreSQL):

Dependency Version
asyncpg ≥ 0.29

Optional (Dashboard):

Dependency Version
streamlit ≥ 1.35
graphviz ≥ 0.20
pandas ≥ 2.0

Installation

1. Clone the repository

git clone https://github.com/Shubhamnegi/dag-planner-mcp.git
cd dag-planner-mcp

2. Create and activate a virtual environment

python -m venv .venv
source .venv/bin/activate        # Linux / macOS
.venv\Scripts\activate           # Windows

3. Install the package

SQLite (dev — no extra dependencies):

pip install -e .

PostgreSQL (prod):

pip install -e ".[postgres]"

With development/test dependencies:

pip install -e ".[dev]"

With Streamlit dashboard:

pip install -e ".[dashboard]"

Database Configuration

The server is controlled entirely via the DATABASE_URL environment variable. Tables are created automatically on first start.

SQLite (development)

# Default — creates dag_planner.db in the current directory
export DATABASE_URL="sqlite:///dag_planner.db"

# Absolute path
export DATABASE_URL="sqlite:////home/user/data/dag_planner.db"

# In-memory (testing only — data lost on exit)
export DATABASE_URL="sqlite:///:memory:"

No additional setup is required for SQLite.

PostgreSQL (production)

export DATABASE_URL="postgresql://user:password@localhost:5432/dag_planner"

Create the database first:

CREATE DATABASE dag_planner;

Then start the server — SQLAlchemy will create all tables automatically.

For connection pooling / SSL in production you can pass extra query parameters:

export DATABASE_URL="postgresql://user:password@host:5432/dag_planner?sslmode=require"

Environment Variables

Variable Default Description
DATABASE_URL sqlite:///dag_planner.db SQLAlchemy connection URL (SQLite or PostgreSQL)
MCP_HOST 127.0.0.1 Host to bind when using HTTP transport
MCP_PORT 8000 Port to bind when using HTTP transport

Running the server

stdio (recommended for Claude Desktop and most MCP clients)

dag-planner-mcp
# or
python -m dag_planner_mcp.server

The server reads from stdin and writes to stdout — no port is opened.

Streamable HTTP

dag-planner-mcp --transport streamable-http --host 0.0.0.0 --port 8000

The MCP endpoint will be available at:

http://localhost:8000/mcp

Using with Claude Desktop (stdio)

The recommended approach is to use uvx so no manual installation is needed (see Quick start with uvx above).

If you prefer to point at a locally installed binary:

  1. Open the Claude Desktop configuration file:

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
    • Windows: %APPDATA%\Claude\claude_desktop_config.json
  2. Add the server under mcpServers:

{
  "mcpServers": {
    "dag-planner-mcp": {
      "command": "/path/to/.venv/bin/dag-planner-mcp",
      "env": {
        "DATABASE_URL": "sqlite:////home/user/data/dag_planner.db"
      }
    }
  }
}

Replace /path/to/.venv/bin/dag-planner-mcp with the absolute path to the installed script (run which dag-planner-mcp after installation).

  1. Restart Claude Desktop. The 22 DAG planner tools will appear in the tools panel.

Using with other MCP clients (streamable HTTP)

Start the server in HTTP mode:

DATABASE_URL="sqlite:///dag_planner.db" \
dag-planner-mcp --transport streamable-http --host 0.0.0.0 --port 8000

Then point your MCP client at:

http://localhost:8000/mcp

Example: Cursor IDE

{
  "mcpServers": {
    "dag-planner-mcp": {
      "url": "http://localhost:8000/mcp"
    }
  }
}

Example: Windsurf / Continue / custom agent

from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

async with streamablehttp_client("http://localhost:8000/mcp") as (r, w, _):
    async with ClientSession(r, w) as session:
        await session.initialize()
        result = await session.call_tool("create_workflow_run", {"goal": "Analyze AWS costs"})

Streamlit Dashboard

A read-only Streamlit dashboard ships in the dashboard/ directory. It reads directly from the same database as the MCP server (via DATABASE_URL) and never writes any data.

Pages

Page Description
Overview Summary metric cards, task status bar chart, recent runs
Workflows Paginated & searchable list of all workflow runs
Run Detail Per-run deep-dive: task table, interactive DAG graph, event log, human approvals
Task Detail Full task state including all JSON payloads

Quick start

# Install with dashboard extras
pip install -e ".[dashboard]"

# Point at the same database your MCP server uses
export DATABASE_URL="sqlite:///dag_planner.db"
# — or for PostgreSQL —
export DATABASE_URL="postgresql://user:password@localhost:5432/dag_planner"

# Launch
streamlit run dashboard/app.py

The dashboard opens at http://localhost:8501 by default.

DAG visualization requires the graphviz system package in addition to the Python bindings. Install it with brew install graphviz (macOS) or apt-get install graphviz (Debian/Ubuntu). If the system package is absent the page falls back to a plain adjacency table.


Available MCP Tools

Planning

Tool Description
create_workflow_run Create a new workflow run (returns run_id)
create_plan_graph Define the task DAG for a run (validates for cycles)
replace_plan_branch Cancel downstream tasks and graft a new plan branch

Scheduling

Tool Description
get_ready_tasks List tasks that are ready and unclaimed
claim_task_for_execution Atomically claim a ready task with a time-bounded lease

State Management

Tool Description
mark_task_running Transition a claimed task to running
mark_task_completed Mark done; auto-promotes dependent tasks to ready
mark_task_failed Mark failed with optional retry
mark_task_blocked_human Block a task awaiting human decision
resume_task Resume a human-blocked task after decision

Task I/O

Tool Description
put_task_output Store working or final output
put_task_checkpoint Save an incremental checkpoint
get_task_payload_refs Retrieve all payload data for a task

Query

Tool Description
get_task Full state of a single task
list_tasks List tasks for a run with filters
get_workflow_run Workflow run state
get_blocked_tasks Tasks blocked on human or dependencies
get_dag_edges All DAG edges for a run

Validation

Tool Description
validate_task_output Validate output against the task's JSON Schema contract
validate_dag_acyclic Check a task list for cycles before submitting

Subagent-safe wrappers

Tool Description
get_my_task Narrow task view for a subagent
update_my_progress Update working output and optional checkpoint
submit_my_output Submit final output and complete the task
request_human_input Block task and request a human decision

Orchestrator Loop Example

import json
from mcp import ClientSession
from mcp.client.stdio import stdio_client

async def run():
    async with stdio_client(["dag-planner-mcp"]) as (r, w):
        async with ClientSession(r, w) as session:
            await session.initialize()

            # 1. Create a workflow
            res = await session.call_tool("create_workflow_run", {
                "goal": "Analyze AWS cost spike and send report"
            })
            run_id = json.loads(res.content[0].text)["data"]["run_id"]

            # 2. Define the task DAG
            await session.call_tool("create_plan_graph", {
                "run_id": run_id,
                "tasks": [
                    {
                        "task_key": "fetch_data",
                        "title": "Fetch cost data",
                        "description": "Pull last 3 weeks of AWS cost data",
                        "owner_agent": "data_agent",
                        "depends_on": [],
                        "output_contract": {"type": "object", "required": ["cost_data"]}
                    },
                    {
                        "task_key": "analyze",
                        "title": "Analyze spike",
                        "description": "Identify top services causing the spike",
                        "owner_agent": "analyst_agent",
                        "depends_on": ["fetch_data"],
                        "output_contract": {"type": "object", "required": ["summary"]}
                    }
                ]
            })

            # 3. Execution loop
            while True:
                res = await session.call_tool("get_ready_tasks", {"run_id": run_id})
                tasks = json.loads(res.content[0].text)["data"]["tasks"]

                if not tasks:
                    break  # All done (or blocked)

                for task in tasks:
                    task_id = task["task_id"]
                    await session.call_tool("claim_task_for_execution", {
                        "task_id": task_id, "executor_id": "orchestrator-1"
                    })
                    await session.call_tool("mark_task_running", {"task_id": task_id})

                    # ... dispatch to subagent, collect result ...
                    output = {"summary": "EC2 caused 40% increase"}

                    await session.call_tool("put_task_output", {
                        "task_id": task_id, "output": output, "is_final": True
                    })
                    await session.call_tool("validate_task_output", {"task_id": task_id})
                    await session.call_tool("mark_task_completed", {
                        "task_id": task_id, "final_output": output
                    })

Running Tests

pip install -e ".[dev]"
pytest tests/ -v

All tests use an in-memory SQLite database and require no external services.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dag_planner_mcp-1.0.0.tar.gz (35.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dag_planner_mcp-1.0.0-py3-none-any.whl (21.5 kB view details)

Uploaded Python 3

File details

Details for the file dag_planner_mcp-1.0.0.tar.gz.

File metadata

  • Download URL: dag_planner_mcp-1.0.0.tar.gz
  • Upload date:
  • Size: 35.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dag_planner_mcp-1.0.0.tar.gz
Algorithm Hash digest
SHA256 b91fa87ebc21b99b553f1e94cd47e51a85fb3f1709bc3fe6ad44e005d8771c36
MD5 d130c10095daa22b4f52feeee9858206
BLAKE2b-256 58cc8321f7137dbb6bce4a5db00a53e369e4a07b41ef59d53f12c88372b04203

See more details on using hashes here.

Provenance

The following attestation bundles were made for dag_planner_mcp-1.0.0.tar.gz:

Publisher: publish.yml on Shubhamnegi/dag-planner-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dag_planner_mcp-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: dag_planner_mcp-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 21.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dag_planner_mcp-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 13ba61bc9b2616335d3d7970a30f5edb08f1171a8df54c2fc73214a9a7981914
MD5 137ed66e22581184a5b623bffde620cd
BLAKE2b-256 6a332464b50fab8b061df96a06f5ddd791ae9e85da56a16f0464590e6c87fe80

See more details on using hashes here.

Provenance

The following attestation bundles were made for dag_planner_mcp-1.0.0-py3-none-any.whl:

Publisher: publish.yml on Shubhamnegi/dag-planner-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page