Skip to main content
Glama
dotfrankruan

Workforce Orchestrator MCP

by dotfrankruan

Workforce Orchestrator MCP

A universal execution workforce for Codex and other MCP clients.

The orchestrator turns a planner (Codex, Claude, or any MCP-capable client) into a supervisor over pluggable worker backends: task DAGs, workflows, budgets, roles, presets, acceptance tracking, metrics, durable process supervision, git isolation, and an artifact cache.

The planner thinks. Workers execute. The orchestrator schedules. The supervisor owns state and Git. Humans retain final control.

                         Planner (Codex)
                              │
                              ▼
                    Workforce Orchestrator
                              │
                        Backend Router
                              │
        ┌──────────────┬──────┴───────┬──────────────┐
        ▼              ▼              ▼              ▼
   DeepSeek        OpenCode      OpenAI API     Anthropic API
   Harness         CLI           (direct)       (direct)
        │              │              │              │
        └──────────────┴──────────────┴──────────────┘
                              │
                     isolated workspaces
                     artifacts · metrics · git

Backends

Backend id

Runtime

Session continuation

Durable reattach

Credentials

dsh

DeepSeek Harness CLI (headless profile)

yes

yes

owned by dsh (~/.dsh/.env)

opencode

OpenCode CLI (opencode run --format json)

yes

yes

owned by OpenCode (opencode auth)

openai

Direct OpenAI Chat Completions or Responses API

yes

no (in-process)

OPENAI_API_KEY / config

anthropic

Direct Anthropic Messages API

yes

no (in-process)

ANTHROPIC_API_KEY / config

fake

Local test backend, no API calls

yes

no

none

The registry is deterministic and never silently falls back. Selection order:

  1. explicit backend on the task/workflow task

  2. routing.roles.<role> from ~/.workforce/config.json

  3. routing.default

  4. default_backend

  5. WORKFORCE_DEFAULT_BACKEND

  6. WORKFORCE_BACKEND (unless auto)

  7. first locally available backend in order dsh → opencode → openai → anthropic

  8. dsh

auto is the default, so a fresh install uses whichever runtime is actually available on the machine. An unavailable explicitly-selected backend is a clear error — nothing is auto-installed or silently substituted.

Related MCP server: coding-agent-mcp

What's new in v5.1

  • DSH model selection. The DeepSeek Harness backend can now run a chosen model — per task (spawn_task({ model: "k3-256k" })), per config (backends.dsh.model), or per environment (WORKFORCE_DSH_MODEL). The headless app has no --model flag, so the backend applies selection with the launcher's documented --patch overlay on agent-default-model (provider + model + reasoningEffort), based on facts read locally from dsh --dump-config. No provider API is contacted to discover models.

  • Model discovery. New list_models MCP tool and node dist/cli.js models command list the models the runtime is configured to serve plus the current default. list_backends / get_backend include models + default_model.

  • Universal per-task model. model works on every backend that advertises capabilities.modelSelection (dsh, opencode, openai, anthropic). Backends that don't support it reject the parameter explicitly instead of ignoring it.

  • Per-task model is persisted (schema v7), shown in results/status, honored by continue_worker, included in cache keys, and aggregated in get_system_metrics().models.

  • Backend failure errors now include a bounded, redacted stderr tail — e.g. invalid models surface the runtime's UNKNOWN_MODEL message directly.

Expanded backend support (part of v5.1)

  • Removed all vendor-specific naming. Environment variables, branches, state paths, package/bin names, and messages are now universal.

  • Added OpenCode as a first-class CLI backend with durable JSONL logs, session continuation, usage/tool events, and reattach support.

  • Added direct OpenAI backend: Chat Completions (/chat/completions) or Responses (/responses), with a tool loop.

  • Added direct Anthropic backend: Messages API with a tool loop.

  • Direct API backends expose read_file, write_file, list_directory, and run_shell, scoped to the task workspace.

  • WORKFORCE_BACKEND=auto plus automatic local backend discovery.

  • Workflow token budget is now max_worker_tokens (vendor alias removed).

Quick start

npm install
npm run build

# Optional: see which backends are locally available, and their models
node dist/cli.js backends
node dist/cli.js models

# Start the MCP server on stdio
node dist/cli.js serve   # or: npx workforce-mcp serve

Zero-config behavior depends on what is installed:

  • dsh on PATH (or /usr/local/bin/dsh) → DeepSeek Harness

  • otherwise opencode on PATH → OpenCode

  • otherwise an OpenAI/Anthropic API key in the environment → direct API

  • otherwise the server starts and reports a clear availability error at spawn

Installation

Requirements:

  • macOS or Linux

  • Node.js ≥ 22 (uses built-in node:sqlite; verified on Node 24)

  • git

  • at least one worker backend:

    • DeepSeek Harness CLI, or

    • OpenCode CLI, or

    • an OpenAI-compatible API key, or

    • an Anthropic API key

npm install
npm run build

Codex MCP setup

[mcp_servers.workforce]
command = "node"
args = ["/absolute/path/to/workforce-orchestrator-mcp/dist/cli.js", "serve"]

Each argv element must be its own TOML string. A single "…/cli.js serve" string makes node look for a file literally named cli.js serve.

Optional environment overrides:

[mcp_servers.workforce.env]
WORKFORCE_BACKEND = "auto"
WORKFORCE_MAX_CONCURRENT = "4"
WORKFORCE_ROOT = "~/.workforce/workers"
# Direct API backends:
# OPENAI_API_KEY = "..."
# ANTHROPIC_API_KEY = "..."

Backend configuration (~/.workforce/config.json)

The orchestrator works with zero configuration. The optional config file is the single place to pin executables, choose models, and route roles.

  • First CLI start → if the file is absent, a minimal starter config is written automatically ({"default_backend":"auto", ...}). It pins nothing, so local backend discovery still applies.

  • Existing file → strict JSON (no comments, no YAML), read once at startup and never modified by the server.

  • WORKFORCE_CONFIG → override the config file location (useful for CI, tests, or per-project configs).

  • To start from the fully populated reference instead of the starter:

    mkdir -p ~/.workforce
    cp config.example.json ~/.workforce/config.json
    node dist/cli.js backends

Schema

{
  "default_backend": "auto",
  "backends": {
    "dsh": {
      "command": "/usr/local/bin/dsh",
      "profile": "headless",
      "model": "k3",                 // default model for every dsh run
      "provider": "kimi-coding",     // provider that owns the model
      "reasoning_effort": "max"      // passed through as reasoningEffort
    },
    "opencode": {
      "command": "opencode",
      "model": "anthropic/claude-sonnet-4-5",
      "agent": "build",
      "auto_approve": true,
      "args": []
    },
    "openai": {
      "api_key_env": "OPENAI_API_KEY",
      "base_url": "https://api.openai.com/v1",
      "model": "gpt-4.1",
      "api": "chat_completions",     // or "responses"
      "max_output_tokens": 8192,
      "temperature": 0.2,
      "max_iterations": 48
    },
    "anthropic": {
      "api_key_env": "ANTHROPIC_API_KEY",
      "base_url": "https://api.anthropic.com",
      "model": "claude-sonnet-4-5",
      "api_version": "2023-06-01",
      "max_output_tokens": 8192,
      "max_iterations": 48
    }
  },
  "routing": {
    "default": "dsh",
    "roles": {
      "reviewer": "openai",
      "researcher": "anthropic"
    }
  }
}

All fields are optional. Unknown keys are ignored for forward compatibility. Backend ids referenced in default_backend / routing must be registered, otherwise startup fails with an explicit error.

Credentials

Prefer environment variables over storing secrets in the config file:

Backend

Primary env

Alternate env

OpenAI

WORKFORCE_OPENAI_API_KEY

OPENAI_API_KEY

Anthropic

WORKFORCE_ANTHROPIC_API_KEY

ANTHROPIC_API_KEY

api_key_env lets you name a different environment variable. A custom base_url can point at a local OpenAI-compatible gateway that does not require a key; in that case the backend is considered available even with an empty key.

dsh and opencode own their credentials (for example ~/.dsh/.env and opencode auth); the orchestrator does not read or manage them.

Model selection

Every backend with capabilities.modelSelection accepts a per-task model:

{ "task": "...", "mode": "code", "model": "k3-256k" }

Precedence (first hit wins), per backend:

  1. model on the task / workflow task / continue_worker

  2. backends.<id>.model in ~/.workforce/config.json

  3. <BACKEND>_MODEL environment variable (e.g. WORKFORCE_DSH_MODEL)

  4. The runtime's own default (for dsh: agent-default-model in the profile)

Discover what is available without spending quota (local config only):

node dist/cli.js models          # default backend
node dist/cli.js models dsh      # specific backend

The same data is exposed as the list_models MCP tool and inside list_backends / get_backend (models, default_model).

How dsh applies it. The headless app takes no --model flag, so the backend writes a small --patch overlay next to the task logs (dsh-model.yml) that replaces the agent-default-model entry with provider, model, and reasoningEffort. Base values are read from dsh --dump-config --profile <profile> (a local command; never the network, never credentials). An invalid model is not swallowed: the run fails and the error carries the runtime message, e.g. backend exited with code=1 …; stderr: dsh: UNKNOWN_MODEL: pi-ai provider "kimi-coding" has no configured model "…".

For the other backends the override flows through their native mechanism: opencode --model, OpenAI model field, Anthropic model field.

Environment variables

Variable

Default

Meaning

WORKFORCE_BACKEND

auto

auto, dsh, opencode, openai, anthropic, fake

WORKFORCE_DEFAULT_BACKEND

—

Routing default (overrides WORKFORCE_BACKEND)

WORKFORCE_CONFIG

~/.workforce/config.json

Config file path (created on first start if absent)

WORKFORCE_ROOT

~/.workforce/workers

State root (worktrees, task workspaces, db)

WORKFORCE_DB

<root>/workers.db

SQLite database

WORKFORCE_MAX_CONCURRENT

4

Max parallel tasks

WORKFORCE_DEFAULT_TIMEOUT

3600

Default per-task timeout (s)

WORKFORCE_MAX_TIMEOUT

21600

Timeout ceiling (s)

WORKFORCE_LOG_MAX_BYTES

32768

get_worker_log cap

WORKFORCE_DIFF_MAX_BYTES

65536

Full-diff cap

WORKFORCE_FINAL_TEXT_MAX_CHARS

8000

Final report text cap

WORKFORCE_TERMINATE_GRACE_MS

5000

SIGTERM→SIGKILL grace

WORKFORCE_DSH_COMMAND

/usr/local/bin/dsh or PATH

dsh executable

WORKFORCE_DSH_PROFILE

headless

dsh profile

WORKFORCE_DSH_MODEL

profile default

Default dsh model (e.g. k3-256k)

WORKFORCE_DSH_PROVIDER

profile default

Provider owning the dsh model

WORKFORCE_DSH_REASONING_EFFORT

profile default

e.g. max

WORKFORCE_OPENCODE_COMMAND

opencode

OpenCode executable

WORKFORCE_OPENCODE_MODEL

OpenCode default

provider/model

WORKFORCE_OPENCODE_AGENT

OpenCode default

Agent name

WORKFORCE_OPENCODE_AUTO

true

Pass --auto

WORKFORCE_OPENCODE_ARGS

—

Extra CLI flags (space-separated)

WORKFORCE_OPENAI_API_KEY

—

OpenAI key

WORKFORCE_OPENAI_BASE_URL

https://api.openai.com/v1

OpenAI base URL

WORKFORCE_OPENAI_MODEL

gpt-4.1

OpenAI model

WORKFORCE_OPENAI_API

chat_completions

chat_completions or responses

WORKFORCE_ANTHROPIC_API_KEY

—

Anthropic key

WORKFORCE_ANTHROPIC_BASE_URL

https://api.anthropic.com

Anthropic base URL

WORKFORCE_ANTHROPIC_MODEL

claude-sonnet-4-5

Anthropic model

WORKFORCE_ANTHROPIC_VERSION

2023-06-01

API version header

WORKFORCE_ENABLE_SUBAGENTS

false

Allow research/general subagent delegation

WORKFORCE_MAX_SUBAGENT_DEPTH

1

Subagent depth limit

WORKFORCE_MAX_SUBAGENTS_PER_TASK

3

Subagent count limit

MCP tools

Orchestration

Tool

Purpose

create_workflow

Key-based task DAG; shared workspace; budgets; failure policy; cycles rejected.

run_workflow_preset

Expand a built-in preset around a goal (options.dry_run = plan only).

list_presets / list_roles

Built-in presets and role templates.

get_workflow / list_workflows

Transparent plan and live status.

wait_workflow

Event-driven wait for terminal state.

cancel_workflow

Cancel all non-terminal tasks; preserves workspaces/artifacts.

get_workflow_result

Compact aggregate: outcomes, artifacts, metrics, warnings.

get_workflow_diff

Integrated diff vs base (stat by default).

review_task_result

Record acceptance (accepted/rejected/needs_revision).

get_task_metrics / get_workflow_metrics / get_system_metrics

Objective counters and quality stats.

Tasks

Tool

Purpose

spawn_task

Spawn any mode with any workspace, deliverables, capabilities, backend, model.

spawn_tasks

Batch-spawn up to 16 independent tasks.

wait_task / wait_tasks

Efficient event-driven waiting (all/any).

get_task_result

Compact result: status, summary, artifacts, deliverables, usage.

list_artifacts / get_artifact / get_artifact_metadata

Artifact metadata and capped content.

get_task_usage

Tokens, steps, tool calls by tool, runs, duration.

list_backends / get_backend

Backend availability, capabilities, factual metadata, model catalog.

list_models

Models a backend serves + its default (local config only, no API call).

Workers (legacy aliases, fully supported)

Tool

Purpose

spawn_worker

spawn_task(mode=code, git_worktree).

get_worker / list_workers

Compact worker status.

continue_worker

Resume the task in the same workspace/backend session.

cancel_worker

Graceful terminate; workspace and changes preserved.

get_worker_result

Legacy git-focused compact result.

get_worker_log / get_worker_diff

Redacted, capped diagnostics.

Task modes

Mode

Purpose

Default workspace

code

Implement, fix, test, debug, commit in an isolated worktree

git_worktree

research

Investigate (web when available), synthesize, record sources.json

temporary

data

Analyze CSV/JSON/SQLite/logs; inputs read-only, outputs as files

directory (if path given)

docs

README/architecture/migration docs

any

file

Batch organize/classify/rename/convert inside the workspace

directory/temporary

ops

Logs/config/service diagnosis; proposals, no destructive changes

directory/temporary

review

Read-only code review; may run tests

git_worktree

general

Generic knowledge work with file deliverables

temporary

Each mode has its own prompt template under src/prompts/.

Workspaces

  • git_worktree — isolated branch workforce/worker/<id> and worktree under ~/.workforce/workers/<repo>-<hash>/<id>/worktree. The orchestrator never merges, pushes, or touches your main branch.

  • directory — existing caller directory, canonicalized; artifact indexing is scoped to it.

  • temporary — fresh per-task directory under the state root, kept after completion.

Workflows, DAGs, and git isolation

  • Workflows share one workspace; git workflows share one integration branch (workforce/workflow/<wf-id>).

  • Each git workflow task gets its own worktree and branch (workforce/task/<id>), materialized from the current integration HEAD.

  • Task commits are cherry-picked onto the integration branch through a per-workflow async mutex. Conflicts abort cleanly and are surfaced with the conflicting files/commits — never auto-resolved.

  • continue_worker on a conflicted task creates a fresh worktree from the latest integration HEAD (workforce/task/<id>-r<N>) and retries integration.

  • Failure policies: stop_dependents (default), continue, cancel_remaining.

  • Budgets: per-task token/time/tool/iteration caps and per-workflow max_worker_tokens, max_duration_seconds, max_concurrent_tasks, max_tasks. Breaches produce terminal budget_exceeded.

Durable supervision

  • Child-process backends (dsh, opencode) write stdout/stderr directly to durable log files, so a supervisor crash does not break the worker.

  • On restart: a live PID with matching identity is reattached (log replay, counters, timeout, budgets); a dead PID with a durable terminal event is finalized normally; a dead PID with no terminal evidence becomes interrupted. Exit codes are never fabricated.

  • Graceful server shutdown detaches workers instead of killing them. Only cancel_worker, cancel_workflow, timeout, or budget terminate them.

  • Direct API backends (openai, anthropic) run in-process and cannot be reattached; an in-flight request becomes interrupted on restart, with the workspace and artifacts preserved.

Git ownership

Workers edit and test files. The supervisor verifies and commits successful changes on git worktrees:

  • commit message from a suggested_commit_message: line in the final report, or workforce/worker/<task-id>: apply delegated changes;

  • worker-created commits are accepted, remaining dirty files are finalized in a follow-up commit;

  • cancelled / timed-out / failed runs are never auto-committed;

  • commit identity uses the repo's existing user.name/user.email, with a fallback identity only when missing;

  • supervisor git commands: status, diff, add, commit, rev-parse, log, cherry-pick (+--abort), worktree, branch. Never push, merge, reset, clean, or rebase.

Waiting and compact context

Do not poll. wait_task / wait_tasks / wait_workflow are event-driven and return as soon as terminal state is reached (or the wait budget expires). A wait timeout never cancels a worker.

Compact results contain status, summary, artifact metadata, usage, and warnings. Thinking, raw tool output, full logs, full datasets, and giant diffs never enter context automatically. Fetch them explicitly with get_artifact, get_worker_log, or get_worker_diff; all are capped and redacted.

Deliverables and artifacts

deliverables: ["report.md", ...] is written into the worker prompt as a hard requirement and verified on disk at completion. Missing files are recorded as deliverables_missing (the task can still be completed).

Every produced file is indexed in SQLite with path, mime type, size, and sha256. Artifacts must live inside the task workspace; arbitrary paths are rejected. Binary artifacts return metadata only.

Roles and presets

Built-in roles: implementer, tester, researcher, reviewer, docs_writer, data_analyst, debugger, ops_analyst.

Built-in presets: bug_fix, feature_development, quality_audit, research_report, data_analysis. Presets are transparent DAGs — inspect them with list_presets / get_workflow, or dry-run with run_workflow_preset({options:{dry_run:true}}).

CLI

node dist/cli.js serve
node dist/cli.js workers|tasks [--status S] [--limit N]
node dist/cli.js task <id>
node dist/cli.js inspect <id>
node dist/cli.js artifacts <id>
node dist/cli.js artifact <id> <path> [--max-bytes N]
node dist/cli.js usage <id>
node dist/cli.js logs <id> [--lines N]
node dist/cli.js diff <id> [--full]
node dist/cli.js cancel <id>
node dist/cli.js workflows
node dist/cli.js workflow <id>
node dist/cli.js workflow-wait <id> [--timeout S]
node dist/cli.js workflow-cancel <id>
node dist/cli.js review-task <id> <accepted|rejected|needs_revision> [--feedback "..."]
node dist/cli.js task-metrics <id> | workflow-metrics <id> | metrics
node dist/cli.js roles | presets | cache-stats
node dist/cli.js backends | backend <id>

Development

npm run build
npm test                 # unit + integration (fake/local backends, temp repos)
npm run test:unit
npm run test:integration

Smoke / live E2E scripts:

node scripts/mcp-smoke.mjs /path/to/git/repo   # MCP protocol smoke (fake backend)
node scripts/real-dsh-e2e.mjs                  # live dsh coding E2E
node scripts/research-e2e.mjs                  # live research E2E
node scripts/wait-e2e.mjs                      # live parallel wait E2E
node scripts/workflow-e2e.mjs                  # live 3-task DAG E2E
node scripts/parallel-e2e.mjs                  # live parallel git writers E2E
node scripts/reattach-e2e.mjs                  # live supervisor-restart reattach E2E

Security

  • Subprocess backends: argv-array spawn only; prompts/session ids cannot inject shell commands.

  • Direct API backends: file tools resolve paths strictly inside the task workspace. run_shell is an intentional agent capability and executes in that workspace; do not run untrusted models on machines you cannot afford to lose.

  • Credentials: dsh/OpenCode credentials are never read. API keys are read only from the configured environment variables and are never emitted in results, logs, diffs, artifacts, or errors (all output passes a redaction filter).

  • Paths: repo_path/workspace.path are canonicalized and validated; all state lives under the worker root; artifact/deliverable/diff paths must be relative and traversal-free.

  • Ops mode: prompt-level prohibition of sudo/destructive commands/SSH/system changes; proposals over direct modification. Advisory, not a hard sandbox.

  • Process ownership: PID-tracked with start-token identity; reconciliation never assumes liveness from a bare PID.

Known limitations

  • Direct API backends are in-process: no durable reattach across supervisor restarts, and their shell tool inherits the server's permissions.

  • Token budgets are best-effort, checked per backend event; a run can overshoot within one step.

  • Test pass/fail in compact results is heuristic (from the final report); git facts and deliverables are verified directly.

  • Directory-workspace artifact discovery is mtime-based.

  • Capabilities are advisory (prompt-level), not a security sandbox.

  • Artifact cache is opt-in and only for dependency-free tasks.

  • Subagent support is prompt/config only; the runtime manages subagents.

  • No automatic worktree/workspace garbage collection (manual, by design).

License

Licensed under the Apache License, Version 2.0. Copyright 2026 Frank Ruan.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    A local-first MCP orchestration server that uses Codex as lead planner and Antigravity as host to delegate and review bounded tasks with Git integration and persistent SQLite state.
    Apache 2.0
  • A
    license
    A
    quality
    B
    maintenance
    A task-level STDIO MCP server that lets Codex or any other MCP client hand off scoped coding jobs to an asynchronous worker agent which reads the code, edits files, and runs tests, while the client keeps ownership of planning and acceptance. Exposes submit, wait, query, follow-up, and cancel tools so multiple clients can queue and monitor tasks against a chosen project root.
    5
    1
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables a primary agent to dispatch, wait on, and supervise multiple parallel Codex CLI workers, each running in its own isolated Git worktree with conflict-checked path ownership. Persists every worker's state, goals, and event stream to disk so work can be tracked, resumed, reconnected, searched, and cancelled across restarts.
    941 npm
    3
    MIT