Back to Browse

Human Dispatch MCP Server

Developer ToolsModerate6.8MCP RegistryLocal
Free

Server data from the Official MCP Registry

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

About

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

Security Report

6.8
Moderate6.8Moderate Risk

Valid MCP server (2 strong, 2 medium validity signals). 4 known CVEs in dependencies (0 critical, 3 high severity) Package registry verified. Imported from the Official MCP Registry.

11 files analyzed ยท 5 issues found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

env_vars

Check that this permission is expected for this type of plugin.

HTTP Network Access

Connects to external APIs or services over the internet.

What You'll Need

Set these up before or after installing:

API key for the RentAHuman.ai backendRequired

Environment variable: RENTAHUMAN_API_KEY

AWS access key ID for the Amazon Mechanical Turk backendRequired

Environment variable: MTURK_ACCESS_KEY_ID

AWS secret access key for the Amazon Mechanical Turk backendRequired

Environment variable: MTURK_SECRET_ACCESS_KEY

Set to "false" to use MTurk production environment (defaults to sandbox mode)Optional

Environment variable: MTURK_SANDBOX

Webhook URL for the manual backend to send task notificationsOptional

Environment variable: MANUAL_WEBHOOK_URL

How to Install

Add this to your MCP configuration file:

{
  "mcpServers": {
    "io-github-zyntarasystems-human-dispatch-mcp": {
      "env": {
        "MTURK_SANDBOX": "your-mturk-sandbox-here",
        "MANUAL_WEBHOOK_URL": "your-manual-webhook-url-here",
        "RENTAHUMAN_API_KEY": "your-rentahuman-api-key-here",
        "MTURK_ACCESS_KEY_ID": "your-mturk-access-key-id-here",
        "MTURK_SECRET_ACCESS_KEY": "your-mturk-secret-access-key-here"
      },
      "args": [
        "-y",
        "human-dispatch-mcp"
      ],
      "command": "npx"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

human-dispatch-mcp

๐ŸŒ humandispatch.ai โ€” Homepage & provider docs

A universal dispatch layer for AI-agent-to-human task routing โ€” Any business (law firms, VA services, freelancers, agencies) can plug in via webhooks and start receiving AI-dispatched tasks in minutes.

Routes tasks to registered webhook providers with smart matching, fallback chains, and proof-of-completion tracking. Any service provider registers a webhook, and the router matches tasks to providers based on capabilities, region, and budget.

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 fallback)
cp .env.example .env

# 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.

Test sequence:

  1. List backends โ€” call human_list_backends to see webhook_provider and manual

  2. Register a provider โ€” call human_register_provider:

{
  "name": "Test Provider",
  "webhook_url": "https://webhook.site/your-uuid",
  "webhook_secret": "a-secret-that-is-at-least-32-chars-long!",
  "categories": ["digital_micro"],
  "task_types": ["digital"],
  "regions": ["*"],
  "min_budget_usd": 0,
  "max_budget_usd": 500,
  "max_concurrent_tasks": 10
}
  1. Dispatch a task โ€” call human_dispatch_task with Raw JSON input mode:
{
  "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
}

The task should route to your registered provider. If no providers match, it falls through to the manual backend.

MCP Client Configuration

Claude Desktop / Cursor / Any MCP Client

{
  "mcpServers": {
    "human-dispatch": {
      "command": "npx",
      "args": ["human-dispatch-mcp"]
    }
  }
}

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.

Required: HTTP transport refuses to start without MCP_AUTH_TOKEN set. All POST /mcp requests must include Authorization: Bearer <MCP_AUTH_TOKEN>. The /callbacks/task/:taskId endpoint uses HMAC-signature auth instead โ€” providers do not see the bearer token.

{
  "mcpServers": {
    "human-dispatch": {
      "command": "npx",
      "args": ["human-dispatch-mcp"],
      "env": {
        "TRANSPORT": "http",
        "PORT": "3000",
        "MCP_AUTH_TOKEN": "a-long-random-string-32-chars-or-more"
      }
    }
  }
}

Tools Reference

ToolDescription
human_dispatch_taskSubmit a task to be completed by a human worker via the best matching provider
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
human_register_providerRegister a webhook provider to receive dispatched tasks
human_list_providersList registered providers with stats and filters
human_remove_providerDeregister a webhook provider

Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   AI Agent   โ”‚
โ”‚ (Claude, etc)โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
       โ”‚ MCP Protocol (stdio or HTTP)
       โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚     human-dispatch-mcp Server        โ”‚
โ”‚                                      โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ Task Store โ”‚  โ”‚ Provider       โ”‚  โ”‚
โ”‚  โ”‚ (in-memory)โ”‚  โ”‚ Registry       โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                          โ”‚           โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚   Router   โ”‚โ”€โ”€โ”‚  Webhook       โ”‚  โ”‚
โ”‚  โ”‚  (scoring) โ”‚  โ”‚  Provider      โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚  Adapter       โ”‚  โ”‚
โ”‚         โ”‚        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚         โ”‚                โ”‚           โ”‚
โ”‚         โ”‚    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
โ”‚         โ”‚    โ”‚ Provider A (law)    โ”‚ โ”‚
โ”‚         โ”‚    โ”‚ Provider B (VA)     โ”‚ โ”‚
โ”‚         โ”‚    โ”‚ Provider C (photos) โ”‚ โ”‚
โ”‚         โ”‚    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
โ”‚         โ–ผ                            โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      โ”‚
โ”‚  โ”‚   Manual   โ”‚ (always-on fallback) โ”‚
โ”‚  โ”‚  Adapter   โ”‚                      โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

For Service Providers

Any business can register as a provider to receive AI-dispatched tasks. Here's how:

1. Set up a webhook endpoint

Your endpoint receives POST requests with these headers:

HeaderDescription
x-dispatch-signaturesha256=<hmac_hex> โ€” HMAC-SHA256 of the request body using your shared secret
X-Dispatch-EventEvent type: task.new, task.cancel, or provider.verify
X-Dispatch-TaskIdUUID of the task

2. Handle task.new events

Request body:

{
  "payload_version": 1,
  "event": "task.new",
  "task_id": "uuid",
  "description": "What needs to be done",
  "category": "photo_video",
  "task_type": "physical",
  "location": { "address": "123 Main St", "region": "US" },
  "budget": { "max_usd": 25, "currency": "USD" },
  "deadline": { "complete_by": "2026-04-10T18:00:00Z", "urgency": "medium" },
  "proof_required": ["photo", "gps_checkin"],
  "quality_sla": "medium"
}

payload_version is the request-shape version; pin your parser to a known version and reject unknown ones. Today only 1 is sent.

Respond with:

{ "accepted": true, "external_id": "your-internal-id" }

Or reject:

{ "accepted": false, "reason": "Outside service area" }

Handle provider.verify events

When a provider is registered, the server immediately POSTs a provider.verify event to confirm the endpoint is reachable and willing. A 200 alone is not enough โ€” your endpoint must return { "verified": true } in the JSON body. Anything else (missing field, false, non-JSON) marks verification as unreachable. This makes registration require explicit consent from your endpoint, not just URL reachability.

3. Report completion (HTTP transport only)

POST to http://<server>/callbacks/task/<task_id> with headers:

  • x-provider-id: Your provider UUID
  • x-dispatch-signature: sha256=<hmac_hex> of the body
{
  "status": "completed",
  "proof": [
    { "type": "photo", "url": "https://...", "submitted_at": "2026-04-10T12:00:00Z" }
  ],
  "actual_cost_usd": 20,
  "notes": "Task completed successfully"
}

4. Verify HMAC signatures

Always verify incoming webhooks using your shared secret:

const crypto = require('crypto');
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));

HMAC canonicalization contract (load-bearing): the signature is computed over the exact bytes the request was POSTed with, not over a re-serialized JSON object. When you send a callback, sign the byte string you put on the wire โ€” do not parse the body, re-stringify it, and sign that, because key ordering or whitespace may differ. Use JSON.stringify(payload) once, capture the resulting string, sign that string, send that string. The server applies the same rule on the receiving side: it captures the raw request body buffer before any JSON parser touches it.

Smart Routing

The router automatically picks the best backend based on:

  1. Agent preferences โ€” preferred_backends and fallback_chain are honored first
  2. Provider matching โ€” category, task type, region, and budget compatibility
  3. Reliability โ€” providers with higher completion rates are tried first
  4. Speed โ€” faster providers score higher
  5. 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()

        # Register a provider first
        await client.call_tool("human_register_provider", {
            "name": "Photo Service Co",
            "webhook_url": "https://photos.example.com/webhook",
            "webhook_secret": "your-secret-that-is-at-least-32-characters",
            "categories": ["photo_video"],
            "task_types": ["physical"],
            "regions": ["US"],
            "min_budget_usd": 5,
            "max_budget_usd": 100,
            "max_concurrent_tasks": 20
        })

        # 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",
                "region": "US"
            },
            "budget": {"max_usd": 15, "currency": "USD"},
            "deadline": {
                "complete_by": "2026-01-15T18:00:00Z",
                "urgency": "medium"
            },
            "proof_required": ["photo", "gps_checkin"],
            "quality_sla": "medium"
        })
        print(result)

asyncio.run(dispatch_photo_task())

Environment Variables

VariableDefaultDescription
TRANSPORTstdioTransport mode: stdio or http
PORT3000HTTP port (when TRANSPORT=http)
MCP_AUTH_TOKENโ€”Bearer token required on every POST /mcp request when TRANSPORT=http. The HTTP transport refuses to start if unset.
MANUAL_WEBHOOK_URLโ€”Webhook URL for manual task notifications
PROVIDERS_CONFIGโ€”JSON array of provider objects to pre-seed on startup

Security

This server processes outbound HTTP requests on behalf of its callers and is intended to run inside trusted infrastructure. The relevant guarantees:

  • HTTP transport requires authentication. MCP_AUTH_TOKEN is mandatory; the server refuses to start without it. Bearer comparison is constant-time (timingSafeEqual).
  • DNS-rebinding protection is enabled on POST /mcp. The transport rejects requests whose Host header points at anything other than the configured loopback.
  • Outbound URL guard. Every webhook URL the server fetches (provider registration, MANUAL_WEBHOOK_URL, callback_url, proof URLs) goes through a structured validator: HTTPS only, no loopback, no RFC1918 / link-local / unique-local hosts, with a DNS resolution check at fetch time to defeat last-second rebinds. There is no opt-out โ€” use a public tunnel (ngrok, cloudflared) for local testing.
  • Inbound callbacks are authenticated by HMAC, not by IP. Each provider registers its own webhook secret. The server verifies x-dispatch-signature over the raw request bytes before parsing JSON. A per-provider token bucket limits callback flood (30 burst, 5/sec sustained).
  • Terminal-state guard. Once a task reaches completed, failed, or cancelled, callbacks for that task are rejected with 409. This blocks replays, late provider retries, and provider-driven status flips.
  • Webhook payload versioning. All outbound bodies carry payload_version and event discriminators. Pin your parser; reject unknown versions.
  • Webhook secrets never leave the server. Provider data returned by MCP tools is sanitized to drop webhook_secret. The same field never appears in logs.
  • No persistence. Tasks, providers, and per-task state live in memory. Restarting the server discards all state. If you operate this in production, terminate it cleanly so in-flight tasks fail fast rather than hang in providers.

If you discover a security issue, please open a private security advisory on GitHub rather than a public issue.

Roadmap

  • Persistent provider registry (SQLite / PostgreSQL)
  • Task expiration and automatic retry
  • Provider quality scoring and feedback loops
  • Cost estimation before dispatch
  • Batch task submission
  • Provider dashboard / admin UI
  • OAuth-based provider authentication

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

License

MIT

Reviews

No reviews yet

Be the first to review this server!