# Task Graph Mcp

> MCP server for agent task workflows with phases, prompts, gates, and multi-agent coordination

- **Type:** MCP server
- **Install:** `agentstack add mcp-oortonaut-task-graph-mcp`
- **Verified:** Pending review
- **Seller:** [Oortonaut](https://agentstack.voostack.com/s/oortonaut)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.3.0
- **License:** Apache-2.0
- **Upstream author:** [Oortonaut](https://github.com/Oortonaut)
- **Source:** https://github.com/Oortonaut/task-graph-mcp

## Install

```sh
agentstack add mcp-oortonaut-task-graph-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Task Graph MCP Server

**Agent task workflows that actually work.**

When you have AI agents working on complex tasks, things go wrong fast. Agents lose context, skip steps, forget to coordinate. Task Graph solves this with structured workflows: phases to guide work, prompts for automatic guidance, gates to enforce quality, and coordination primitives for multi-agent scenarios—all through the Model Context Protocol.

## Why Task Graph?

**The problem**: You've got complex tasks that need structured execution. Maybe a single agent working through phases, or multiple agents coordinating in parallel. Without proper workflows, agents lose track, skip steps, and produce inconsistent results.

**What you get**:

- **Structured workflows** — Phases (explore, implement, review, test) guide agents through work. Transition prompts provide automatic guidance at each step.
- **Quality gates** — Require tests to pass, code to be committed, or reviews to complete before transitions. Enforce your standards automatically.
- **Ready-to-use topologies** — Pre-built workflows for solo work, parallel swarms, specialist relays, or hierarchical delegation. Start immediately, customize later.
- **Configurable workflows** — Define your own states, phases, prompts, and gates. Match your process, not ours.
- **Multi-agent coordination** — Advisory file locks, DAG dependencies, atomic claiming. No more conflicts or duplicate work.
- **Token-efficient** — Designed for LLM context limits. Compact queries, minimal round-trips, structured outputs.
- **Built-in accounting** — Track tokens, cost, and time per task. Know exactly what your agents are spending.
- **Zero infrastructure** — SQLite with WAL mode. No database server to run. Just point at a file.

## Features

| Feature | Description |
|---------|-------------|
| **Task Hierarchy** | Unlimited nesting with parent/child relationships |
| **DAG Dependencies** | Typed edges (blocks, follows, contains) with cycle detection |
| **Phases** | Categorize work type (explore, implement, review, test, deploy) |
| **Workflows** | Named workflow topologies (solo, swarm, relay, hierarchical) |
| **Transition Prompts** | Automatic agent guidance on status/phase changes |
| **Gates** | Exit requirements for status/phase transitions |
| **Atomic Claiming** | Strict locking with limits and tag-based routing |
| **File Coordination** | Advisory locks with reasons and change polling |
| **Cost Tracking** | Token usage and USD cost per task |
| **Time Tracking** | Automatic accumulation from state transitions |
| **Live Status** | Real-time "current thought" visible to other agents |
| **Full-text Search** | FTS5-powered search across tasks and attachments |
| **Attachments** | Inline content, file references, or media storage |
| **Agent Feedback** | Inter-agent communication with categorized feedback (conditional on config) |
| **Dynamic Overlays** | Runtime workflow customization via add/remove overlay tools |

## Quick Start

```bash
# Install
cargo install task-graph-mcp

# Add to your MCP client (Claude Code, etc.)
```

```json
{
  "mcpServers": {
    "task-graph": {
      "command": "task-graph-mcp"
    }
  }
}
```

```
# Agent workflow (worker_id auto-generated if omitted)
connect(workflow="swarm", tags=["code"])                 → "bright-lunar-swift-fox"
list_tasks(ready=true, agent="bright-lunar-swift-fox")   → claimable work
claim(worker_id="bright-lunar-swift-fox", task="add-auth")  → you own it
update(..., phase="implement")                           → enter implementation phase
thinking(agent="bright-lunar-swift-fox", thought="Adding JWT...")  → visible to others
update(worker_id="bright-lunar-swift-fox", task="add-auth",
       status="completed",
       attachments=[{type:"commit", content:"abc123"}])  → done
```

## Installation

### From crates.io (Recommended)

```bash
cargo install task-graph-mcp
```

### Pre-built Binaries

Download the latest release for your platform from [GitHub Releases](https://github.com/Oortonaut/task-graph-mcp/releases):

| Platform | Download |
|----------|----------|
| Linux (x64) | `task-graph-mcp-x86_64-unknown-linux-gnu.tar.gz` |
| macOS (Intel) | `task-graph-mcp-x86_64-apple-darwin.tar.gz` |
| macOS (Apple Silicon) | `task-graph-mcp-aarch64-apple-darwin.tar.gz` |
| Windows (x64) | `task-graph-mcp-x86_64-pc-windows-msvc.zip` |

Extract and place the binary in your PATH.

### From Source

```bash
git clone https://github.com/Oortonaut/task-graph-mcp.git
cd task-graph-mcp
cargo build --release
```

The binary will be at `target/release/task-graph-mcp`.

## Usage

### As an MCP Server

Add to your MCP client configuration:

```json
{
  "mcpServers": {
    "task-graph": {
      "command": "task-graph-mcp",
      "args": []
    }
  }
}
```

### CLI Options

```
task-graph-mcp [OPTIONS]

Options:
  -c, --config      Path to configuration file
  -d, --database    Path to database file (overrides config)
  -v, --verbose           Enable verbose logging
  -h, --help              Print help
  -V, --version           Print version
```

## Configuration

> **Full reference**: See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for complete configuration documentation including workflows, prompts, gates, roles, and tags.

Create `.task-graph/config.yaml`:

```yaml
server:
  db_path: .task-graph/tasks.db
  media_dir: .task-graph/media  # Directory for file attachments
  skills_dir: .task-graph/skills  # Custom skill overrides
  stale_timeout_seconds: 900
  default_format: json  # or markdown

paths:
  style: relative  # or project_prefixed

auto_advance:
  enabled: false        # Auto-transition unblocked tasks
  target_state: ready   # Target state (requires custom state in states config)
```

### States Configuration

Task states are configurable. Default states: `pending`, `working`, `completed`, `failed`, `cancelled`.

To add a `ready` state for auto-advance:

```yaml
states:
  initial: pending
  disconnect_state: pending  # State for tasks when owner disconnects (must be untimed)
  blocking_states: [pending, working]
  definitions:
    pending:
      exits: [ready, working, cancelled]
    ready:
      exits: [working, cancelled]
    working:
      exits: [completed, failed, pending]
      timed: true    # Time in this state counts toward time_actual_ms
    completed:
      exits: []
    failed:
      exits: [pending]
    cancelled:
      exits: []

auto_advance:
  enabled: true
  target_state: ready
```

See [SCHEMA.md](SCHEMA.md#states-configuration) for full documentation on state definitions.

### Dependencies Configuration

Dependency types define how tasks relate to each other. Default types: `blocks`, `follows`, `contains`, `duplicate`, `see-also`, `relates-to`.

```yaml
dependencies:
  definitions:
    blocks:
      display: horizontal  # Same-level relationship
      blocks: start        # Blocks claiming the dependent task
    follows:
      display: horizontal
      blocks: start
    contains:
      display: vertical    # Parent-child relationship
      blocks: completion   # Blocks completing the parent
    duplicate:
      display: horizontal
      blocks: none         # Informational only
    see-also:
      display: horizontal
      blocks: none
    relates-to:
      display: horizontal
      blocks: none
```

| Property | Values | Description |
|----------|--------|-------------|
| `display` | `horizontal`, `vertical` | Visual relationship (same-level vs parent-child) |
| `blocks` | `none`, `start`, `completion` | What the dependency blocks |

### Attachments Configuration

Preconfigured attachment keys provide default MIME types and modes, reducing boilerplate when attaching common content types.

```yaml
attachments:
  unknown_key: warn  # allow | warn (default) | reject
  definitions:
    commit:
      mime: text/git.hash
      mode: append
    checkin:
      mime: text/p4.changelist
      mode: append
    meta:
      mime: application/json
      mode: replace
    note:
      mime: text/plain
      mode: append
```

| Property | Values | Description |
|----------|--------|-------------|
| `unknown_key` | `allow`, `warn`, `reject` | Behavior for undefined attachment keys |
| `definitions..mime` | MIME type string | Default MIME type for this key |
| `definitions..mode` | `append`, `replace` | Default mode (append keeps existing, replace overwrites) |

**Built-in defaults**:

| Key | MIME Type | Mode | Use Case |
|-----|-----------|------|----------|
| `commit` | text/git.hash | append | Git commit hashes |
| `checkin` | text/p4.changelist | append | Perforce changelists |
| `changelist` | text/plain | append | Files changed |
| `meta` | application/json | replace | Structured metadata |
| `note` | text/plain | append | General notes |
| `log` | text/plain | append | Log output |
| `error` | text/plain | append | Error messages |
| `output` | text/plain | append | Command/tool output |
| `diff` | text/x-diff | append | Patches and diffs |
| `plan` | text/markdown | replace | Plans and specs |
| `result` | application/json | replace | Structured results |
| `context` | text/plain | replace | Current context/state |

**Usage**:
```
# MIME and mode auto-filled from config:
attach(task="123", name="commit", content="abc1234")
# → mime=text/git.hash, mode=append

attach(task="123", name="meta", content='{"v":1}')
# → mime=application/json, mode=replace (overwrites existing meta)

# Explicit values override defaults:
attach(task="123", name="commit", mime="text/plain", content="override")
```

Environment variables:
- `TASK_GRAPH_CONFIG_PATH`: Path to configuration file (takes precedence over `.task-graph/config.yaml`)
- `TASK_GRAPH_DB_PATH`: Database file path (fallback if no config file)
- `TASK_GRAPH_MEDIA_DIR`: Media directory for file attachments (fallback if no config file)
- `TASK_GRAPH_LOG_DIR`: Log directory path (fallback if no config file)

## MCP Tools

### Worker Management

| Tool | Description |
|------|-------------|
| `connect(worker_id?, tags?, workflow?, force?, db_path?, media_dir?, log_dir?, config_path?, overlays?: str[])` | Register a worker. Optional `workflow` selects named workflow (solo, swarm, relay, hierarchical). Returns `worker_id` and active `paths`. |
| `disconnect(worker_id: worker_str, final_status?: status_str = "pending")` | Unregister worker and release all claims/locks. |
| `list_agents(tags?: str[], file?: filename, task?: task_str, depth?: int, stale_timeout?: int)` | List connected workers with filters. |
| `cleanup_stale(timeout?: int, final_status?: status_str)` | Evict stale workers and release their claims. |
| `add_overlay(worker_id: str, overlay: str)` | Add a dynamic workflow overlay to a connected worker. |
| `remove_overlay(worker_id: str, overlay: str)` | Remove a workflow overlay from a connected worker. |

### Task CRUD

| Tool | Description |
|------|-------------|
| `create(description: str, id?: task_str, parent?: task_str, priority?: int = 5, points?: int, time_estimate_ms?: int, tags?: str[])` | Create a task. Priority 0-10 (higher = more important). |
| `create_tree(tree, parent?, child_type?, sibling_type?)` | Create nested task tree. `child_type` (default: "contains") for parent→child deps, `sibling_type` for sibling deps. |
| `get(task: task_str)` | Get task by ID with attachment metadata and counts. |
| `list_tasks(status?: status_str[], ready?: bool, blocked?: bool, claimed?: bool, owner?: worker_str, parent?: task_str, recursive?: bool, agent?: worker_str, tags_any?: str[], tags_all?: str[], sort_by?: str, sort_order?: str, limit?: int, offset?: int)` | Query tasks with filters. Use `ready=true` for claimable tasks. |
| `update(worker_id: worker_str, task: task_str, status?: status_str, phase?: str, assignee?: worker_str, title?: str, description?: str, priority?: int, points?: int, tags?: str[], needed_tags?: str[], wanted_tags?: str[], time_estimate_ms?: int, reason?: str, force?: bool, attachments?: object[])` | Update task. Status/phase changes auto-manage ownership and trigger prompts. Include `attachments` to record commits/changelists. |
| `delete(worker_id: worker_str, task: task_str, cascade?: bool, reason?: str, obliterate?: bool, force?: bool)` | Delete task. Soft delete by default; `obliterate=true` for permanent. |
| `scan(task: task_str, before?: int, after?: int, above?: int, below?: int)` | Scan task graph in multiple directions. Depth: 0=none, N=levels, -1=all. |
| `search(query: str, limit?: int = 20, include_attachments?: bool, status_filter?: status_str)` | FTS5 search. Supports phrases, prefix*, AND/OR/NOT, title:word. |
| `rename(worker_id: worker_str, task: task_str, new_id: task_str)` | Atomically rename a task ID across all referencing tables. |

### Task Claiming

| Tool | Description |
|------|-------------|
| `claim(worker_id: worker_str, task: task_str, force?: bool)` | Claim a task. Fails if deps unsatisfied, at limit, or lacks tags. Use `force` to steal. |

**Note**: Release via `update(status="pending")`. Complete via `update(status="completed")`. Status changes auto-manage ownership.

### Dependencies

| Tool | Description |
|------|-------------|
| `link(from: task_str\|task_str[], to: task_str\|task_str[], type?: dep_str = "blocks")` | Create dependencies. Types: blocks, follows, contains, duplicate, see-also, relates-to. |
| `unlink(from: task_str\|"*", to: task_str\|"*", type?: dep_str)` | Remove dependencies. Use `*` as wildcard. |
| `relink(prev_from: task_str[], prev_to: task_str[], from: task_str[], to: task_str[], type?: dep_str = "contains")` | Atomically move dependencies (unlink then link). |

### Tracking

| Tool | Description |
|------|-------------|
| `thinking(worker_id: worker_str, thought: str, tasks?: task_str[])` | Broadcast live status. Visible to other workers. Refreshes heartbeat. |
| `task_history(task: task_str, states?: status_str[])` | Get status transition history with time tracking. |
| `project_history(from?: datetime_str, to?: datetime_str, states?: status_str[], limit?: int = 100)` | Project-wide history with date range filters. |
| `log_metrics(worker_id: worker_str, task: task_str, cost_usd?: float, values?: int[8])` | Log metrics (aggregated). |
| `get_metrics(task: task_str\|task_str[])` | Get metrics for task(s). |
| `give_feedback(message: str, category?: str, sentiment?: str, agent_id?: str, tool_name?: str, task_id?: str)` | Record feedback about tools, workflows, or UX. Enabled by default; rejects writes past size limit (default: 1MB). |
| `list_feedback()` | Read the feedback markdown file. |

### File Coordination

| Tool | Description |
|------|-------------|
| `mark_file(worker_id: worker_str, file: filename\|filename[], task?: task_str, reason?: str)` | Mark file(s) to signal intent. Advisory, non-blocking. |
| `unmark_file(worker_id: worker_str, file?: filename\|filename[]\|"*", task?: task_str, reason?: str)` | Remove marks. Use `*` for all. |
| `list_marks(files?: filename[], worker_id?: worker_str, task?: task_str)` | Get current file marks. |
| `mark_updates(worker_id: worker_str)` | Poll for mark changes since last call. |

### Attachments

| Tool | Description |
|------|-------------|
| `attach(task: task_str\|task_str[], name: str, content?: str, mime?: mime_str, file?: filename, store_as_file?: bool, mode?: str)` | Add attachment. Use `file` for reference, `store_as_file` for media storage. |
| `attachments(task: task_str, name?: str, mime?: mime_str)` | Get attachment metadata. Glob patterns supported for name. |
| `detach(worker_id: worker_str, task: task_str, name: str, delete_file?: bool)` | Delete attachment by name. |

### Advanced

| Tool | Description |
|------|-------------|
| `check_gates(task: task_str)` | Check gate requirements before status/phase transition. Returns unsatisfied gates with pass/warn/fail status. |
| `get_advisory(topic?: str, task?: task_str, worker_id?: worker_str)` | Get governance advisory guidance. Without topic: lists all topics. With topic: return

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Oortonaut](https://github.com/Oortonaut)
- **Source:** [Oortonaut/task-graph-mcp](https://github.com/Oortonaut/task-graph-mcp)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.3.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.3.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-oortonaut-task-graph-mcp
- Seller: https://agentstack.voostack.com/s/oortonaut
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
