MCP Hub
Back to servers

human-dispatch-mcp

MCP server that dispatches physical-world tasks to humans through a unified API

Registry
Updated
Apr 3, 2026

Quick Install

npx -y human-dispatch-mcp

human-dispatch-mcp

Plaid for human-in-the-loop — A production-grade MCP server that lets any AI agent dispatch physical-world tasks to humans through a single unified API.

Routes tasks across multiple backends (Amazon Mechanical Turk, RentAHuman.ai, and a manual/webhook fallback) with smart selection, fallback chains, and proof-of-completion tracking.

Quick Start

# Clone and install
git clone https://github.com/zyntarasystems/human-dispatch-mcp.git
cd human-dispatch-mcp
npm install

# Configure (optional — works out of the box with manual backend)
cp .env.example .env
# Edit .env to add API keys for MTurk / RentAHuman

# Build and run
npm run build
node dist/index.js

Testing with MCP Inspector

The easiest way to verify the server is working:

npx @modelcontextprotocol/inspector node dist/index.js

Open http://localhost:5173, enter the proxy session token shown in your terminal, and click Connect.

Once connected, call human_dispatch_task using Raw JSON input mode (the UI's field-by-field mode has parsing issues with nested objects):

{
  "description": "Test task — verify the MCP server is routing correctly",
  "category": "digital_micro",
  "task_type": "digital",
  "budget": { "max_usd": 5, "currency": "USD" },
  "deadline": {
    "complete_by": "2026-04-10T18:00:00Z",
    "urgency": "low"
  },
  "proof_required": ["text_report"],
  "quality_sla": "low",
  "callback_url": null
}

You should get back a task ID with "backend_id": "manual" — the manual backend is always available without any API keys configured.

MCP Client Configuration

Claude Desktop / Cursor / Any MCP Client

Add to your MCP client config:

{
  "mcpServers": {
    "human-dispatch": {
      "command": "npx",
      "args": ["human-dispatch-mcp"],
      "env": {
        "RENTAHUMAN_API_KEY": "your-key-here"
      }
    }
  }
}

HTTP Transport

Note: HTTP transport binds to 127.0.0.1 only. For remote access, place a TLS-terminating reverse proxy (e.g. nginx, Caddy) in front of the server. Never expose the port directly.

{
  "mcpServers": {
    "human-dispatch": {
      "command": "npx",
      "args": ["human-dispatch-mcp"],
      "env": {
        "TRANSPORT": "http",
        "PORT": "3000"
      }
    }
  }
}

Tools Reference

ToolDescription
human_dispatch_taskSubmit a task to be completed by a human worker via the best available backend
human_get_task_statusPoll the current status, worker info, and proof submissions for a task
human_cancel_taskCancel a pending or in-progress task
human_list_tasksList tasks with filters (status, backend, category) and pagination
human_list_backendsShow available backends, their configuration status, and capabilities

Architecture

┌─────────────┐
│   AI Agent   │
│ (Claude, etc)│
└──────┬───────┘
       │ MCP Protocol (stdio or HTTP)
       ▼
┌──────────────────────────────────┐
│     human-dispatch-mcp Server     │
│                                  │
│  ┌────────────┐  ┌────────────┐  │
│  │ Task Store │  │   Router   │  │
│  │ (in-memory)│  │  (scoring) │  │
│  └────────────┘  └─────┬──────┘  │
│                        │         │
│         ┌──────────────┼─────────┤
│         ▼              ▼         ▼
│  ┌───────────┐  ┌───────────┐  ┌────────┐
│  │   MTurk   │  │ RentAHuman│  │ Manual │
│  │  Adapter  │  │  Adapter  │  │Adapter │
│  │(simulated)│  │(simulated)│  │(active)│
│  └───────────┘  └───────────┘  └────────┘
└──────────────────────────────────┘

Backend Adapters

BackendStatusTask TypesRegionsBudget Range
Amazon Mechanical TurkSimulatedDigitalGlobal$0.01 - $100
RentAHuman.aiSimulatedPhysicalUS$5 - $500
Manual / WebhookWorkingAllGlobal$0 - $10,000

Smart Routing

The router automatically picks the best backend based on:

  1. Agent preferencespreferred_backends and fallback_chain are honored first
  2. Compatibility — task type (physical/digital), location requirements, budget range
  3. Speed — faster backends score higher
  4. Reliability — real backends preferred over manual fallback

The manual backend is always available as the ultimate fallback.

Example Agent Usage

Python with LangGraph

import asyncio
from langchain_mcp_adapters.client import MultiServerMCPClient

async def dispatch_photo_task():
    async with MultiServerMCPClient({
        "human": {
            "command": "node",
            "args": ["path/to/human-dispatch-mcp/dist/index.js"],
            "transport": "stdio",
        }
    }) as client:
        tools = client.get_tools()

        # Dispatch a task
        result = await client.call_tool("human_dispatch_task", {
            "description": "Take a photo of the menu board at Starbucks on 5th Ave, NYC",
            "category": "photo_video",
            "task_type": "physical",
            "location": {
                "address": "5th Ave & 42nd St, New York, NY"
            },
            "budget": {"max_usd": 15, "currency": "USD"},
            "deadline": {
                "complete_by": "2025-01-15T18:00:00Z",
                "urgency": "medium"
            },
            "proof_required": ["photo", "gps_checkin"],
            "quality_sla": "medium"
        })
        print(result)

        # Check status later
        status = await client.call_tool("human_get_task_status", {
            "task_id": "<task-id-from-above>"
        })
        print(status)

asyncio.run(dispatch_photo_task())

Environment Variables

VariableDefaultDescription
TRANSPORTstdioTransport mode: stdio or http
PORT3000HTTP port (when TRANSPORT=http)
MTURK_ACCESS_KEY_IDAWS access key for Mechanical Turk
MTURK_SECRET_ACCESS_KEYAWS secret key for Mechanical Turk
MTURK_SANDBOXtrueUse MTurk sandbox environment (must be "true" or "false")
RENTAHUMAN_API_KEYAPI key for RentAHuman.ai
MANUAL_WEBHOOK_URLWebhook URL for manual task notifications

Roadmap

Phase 2

  • Real AWS Mechanical Turk API integration
  • Real RentAHuman.ai API integration
  • TaskRabbit adapter
  • Webhook callback delivery for status updates
  • Persistent storage (SQLite / PostgreSQL)
  • Task expiration and automatic retry
  • Worker quality scoring and feedback
  • Cost estimation before dispatch
  • Batch task submission

Contributing

Adding a New Backend Adapter

  1. Create a new file in src/services/backends/
  2. Extend BaseBackendAdapter
  3. Implement all methods from BackendAdapter interface
  4. Add the backend ID to the BackendId enum in src/types.ts
  5. Register the adapter in src/index.ts
import { BaseBackendAdapter } from "./base.js";
import { BackendCapabilities, BackendId, Task, BackendSubmitResult, BackendStatusResult } from "../../types.js";

export class MyNewAdapter extends BaseBackendAdapter {
  readonly id = BackendId.MY_NEW_BACKEND; // Add to enum first

  getCapabilities(): BackendCapabilities {
    return {
      id: this.id,
      name: "My New Backend",
      supports_physical: true,
      supports_digital: true,
      supports_location: true,
      available_regions: ["US", "EU"],
      min_budget_usd: 1,
      max_budget_usd: 1000,
      avg_completion_minutes: 60,
      requires_api_key: true,
      configured: this.isConfigured(),
    };
  }

  isConfigured(): boolean {
    return !!process.env["MY_BACKEND_API_KEY"];
  }

  async submitTask(task: Task): Promise<BackendSubmitResult> {
    // Your implementation here
  }

  // ... implement getStatus and cancelTask
}

License

MIT

Reviews

No reviews yet

Sign in to write a review