Skip to main content
v1.0Protocol: 2025-03-26

MCP API Reference

Complete developer reference for the DispatchNode MCP server. Covers authentication, the JSON-RPC protocol, all available tools with full I/O schemas, error codes, and SDK examples.

Overview

The DispatchNode MCP server implements the Model Context Protocol (MCP) via the Streamable HTTP transport. It exposes a single endpoint that accepts JSON-RPC 2.0 requests and returns JSON-RPC 2.0 responses.

POSThttps://www.dispatchnode.com/api/mcp

The server supports two access tiers — customer and operator — so AI agents can book jobs without needing an API key, while business owners get full administrative access.

TierAuthToolsWho
CustomerX-Org-Slug header (no key)book_job, check_availability, get_pricingAI agents acting on behalf of a customer
OperatorAuthorization: Bearer dnk_...All 6 toolsBusiness owner's CRM / automation

Authentication

Customer Tier: No API key needed. AI agents visiting a site with the DispatchNode widget can call customer tools by passing the org slug. This works the same way the voice widget does — no credentials required.

Customer Tier (No API Key)

For AI agents acting on behalf of customers (e.g., a wedding planner's Claude assistant booking portapotties). Pass the org slug from the <link> tag's data-org-slug attribute.

Customer Requesthttp
POST /api/mcp HTTP/1.1
Host: www.dispatchnode.com
Content-Type: application/json
X-Org-Slug: eventrestroomrentals

Available tools: book_job, check_availability, get_pricing. Rate limited to 30 req/min and 10 bookings/hour per IP.

Operator Tier (API Key)

For the business owner's own CRM or automation integrations. Full access to all 6 tools.

Key format
dnk_ + 32 random bytes (base64url)
Storage
SHA-256 hash — raw key shown only at creation
Scope
One key = one organization. No cross-tenant access.
Revocation
Instant — revoked keys fail on next request
Prefix
First 12 chars visible for identification (e.g. dnk_a1b2c3d4)
Usage tracking
lastUsedAt updated on each successful validation
Operator Requesthttp
POST /api/mcp HTTP/1.1
Host: www.dispatchnode.com
Content-Type: application/json
Authorization: Bearer dnk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0

JSON-RPC Protocol

All communication uses JSON-RPC 2.0 over HTTP POST. Every request must include:

FieldTypeDescription
jsonrpc"2.0"Must be exactly "2.0"
idstring | numberRequest identifier — echoed in the response
methodstringOne of: initialize, tools/list, tools/call
paramsobjectMethod parameters (optional for initialize and tools/list)

Available methods:

initializeEstablish a session. Returns server info, capabilities, and protocol version.
notifications/initializedClient acknowledgment after initialize. No meaningful response.
tools/listReturns all available tools with their JSON Schema input definitions.
tools/callExecute a tool. Requires params.name and params.arguments.

Session Lifecycle

A typical MCP session follows this sequence:

1
Initialize
{ "jsonrpc": "2.0", "id": 1, "method": "initialize" }
2
Server returns capabilities
{ "protocolVersion": "2025-03-26", "serverInfo": { "name": "dispatchnode", "version": "1.0.0" }, "capabilities": { "tools": {} } }
3
List tools (optional)
{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }
4
Call tools (repeat)
{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "book_job", "arguments": { ... } } }
Note:Unlike WebSocket-based MCP transports, Streamable HTTP is stateless. Each POST request is independent — you don't need to maintain a persistent connection. The initialize step is optional but recommended.

Tools Reference

6 tools

Each tool accepts typed arguments and returns a JSON-RPC result with a content array containing a text item with the JSON-stringified response.

book_job

TOOL

Book a new service job. Finds or creates a customer by phone number, resolves the service type by slug, creates a Job record with SCHEDULED status, and returns the full booking confirmation.

Input Parameters

ParameterTypeRequiredDescription
customerNamestringrequiredCustomer's full name
customerPhonestringrequiredE.164 format phone number (+1XXXXXXXXXX)
customerEmailstringoptionalCustomer email address
serviceAddressstringrequiredFull service location address
scheduledStartstringrequiredISO 8601 datetime (e.g. 2026-04-15T09:00:00Z)
scheduledEndstringoptionalISO 8601 datetime for job end
serviceTypestringoptionalService type slug (e.g. 'grease-trap-450-gal')
notesstringoptionalDispatch notes for the technician
prioritystringoptionalOne of: normal, urgent, emergency

Response Fields

FieldTypeDescription
jobIdstringUUID of the created job
statusstringAlways 'SCHEDULED' for new bookings
scheduledStartstringISO 8601 confirmed start time
scheduledEndstring | nullISO 8601 end time if provided
serviceAddressstringConfirmed service address
priorityLevelstringConfirmed priority level
customerNamestringCustomer name
customerPhonestringCustomer phone
createdAtstringISO 8601 creation timestamp
Requestjson
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "book_job",
    "arguments": {
      "customerName": "John Smith",
      "customerPhone": "+15551234567",
      "customerEmail": "[email protected]",
      "serviceAddress": "123 Main St, Dallas, TX",
      "scheduledStart": "2026-04-15T09:00:00Z",
      "serviceType": "grease-trap-450-gal",
      "priority": "normal"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [{
      "type": "text",
      "text": "{\n  \"jobId\": \"a1b2c3d4-..\",\n  \"status\": \"SCHEDULED\",\n  \"scheduledStart\": \"2026-04-15T09:00:00Z\",\n  \"serviceAddress\": \"123 Main St, Dallas, TX\",\n  \"priorityLevel\": \"normal\",\n  \"customerName\": \"John Smith\",\n  \"customerPhone\": \"+15551234567\"\n}"
    }]
  }
}

check_availability

TOOL

Check available time slots for a date range. Returns existing bookings, transit buffer configuration, business hours, and timezone so the caller can compute open slots.

Input Parameters

ParameterTypeRequiredDescription
startDatestringrequiredStart of range (ISO 8601)
endDatestringrequiredEnd of range (ISO 8601)
serviceTypestringoptionalService type slug to check duration requirements

Response Fields

FieldTypeDescription
dateRangeobject{ start, end } ISO 8601 strings
existingBookingsnumberCount of bookings in range
bookedSlotsarrayArray of { start, end, address }
transitBufferMinsnumberMinutes of travel buffer between jobs
timezonestringIANA timezone (e.g. America/Chicago)
businessHoursobject | nullBusiness hours config if set
Requestjson
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "check_availability",
    "arguments": {
      "startDate": "2026-04-15T00:00:00Z",
      "endDate": "2026-04-16T00:00:00Z"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [{
      "type": "text",
      "text": "{\n  \"dateRange\": { \"start\": \"2026-04-15T00:00:00Z\", \"end\": \"2026-04-16T00:00:00Z\" },\n  \"existingBookings\": 3,\n  \"bookedSlots\": [\n    { \"start\": \"2026-04-15T09:00:00Z\", \"end\": \"2026-04-15T10:00:00Z\", \"address\": \"123 Main St\" },\n    { \"start\": \"2026-04-15T11:00:00Z\", \"end\": \"2026-04-15T12:30:00Z\", \"address\": \"456 Oak Ave\" }\n  ],\n  \"transitBufferMins\": 30,\n  \"timezone\": \"America/Chicago\",\n  \"businessHours\": null\n}"
    }]
  }
}

list_jobs

TOOL

List jobs for the organization with optional status filtering and pagination. Returns jobs with customer information, scheduling details, and quoted amounts.

Input Parameters

ParameterTypeRequiredDescription
statusstringoptionalFilter by status: LEAD, QUOTED, SCHEDULED, IN_PROGRESS, COMPLETED, CANCELLED
limitnumberoptionalMax results per page (default: 20, max: 100)
offsetnumberoptionalPagination offset (default: 0)

Response Fields

FieldTypeDescription
jobsarrayArray of job objects with customer details
totalnumberTotal matching jobs (for pagination)
limitnumberApplied limit
offsetnumberApplied offset
Requestjson
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "list_jobs",
    "arguments": {
      "status": "SCHEDULED",
      "limit": 5
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [{
      "type": "text",
      "text": "{\n  \"jobs\": [\n    {\n      \"id\": \"a1b2..\",\n      \"status\": \"SCHEDULED\",\n      \"priorityLevel\": \"normal\",\n      \"serviceAddress\": \"123 Main St\",\n      \"scheduledStart\": \"2026-04-15T09:00:00Z\",\n      \"customer\": {\n        \"name\": \"John Smith\",\n        \"phoneNumber\": \"+15551234567\",\n        \"email\": \"[email protected]\"\n      }\n    }\n  ],\n  \"total\": 12,\n  \"limit\": 5,\n  \"offset\": 0\n}"
    }]
  }
}

get_pricing

TOOL

Retrieve service pricing, deposit requirements, and platform plan metadata. Pass a service type slug to filter to a specific service, or omit to get all active services.

Input Parameters

ParameterTypeRequiredDescription
serviceTypestringoptionalService type slug (omit to return all)

Response Fields

FieldTypeDescription
servicesarrayArray of service types with pricing
platformobjectPlan label, monthly price, overage rate, minutes allowance
Requestjson
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "get_pricing",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "content": [{
      "type": "text",
      "text": "{\n  \"services\": [\n    {\n      \"slug\": \"grease-trap-450-gal\",\n      \"name\": \"450 Gal Grease Trap Pump\",\n      \"durationMins\": 60,\n      \"priceBaseCents\": 35000,\n      \"requiresDeposit\": true,\n      \"depositCents\": 10000,\n      \"depositType\": \"fixed\"\n    }\n  ],\n  \"platform\": {\n    \"plan\": \"DispatchNode Pro\",\n    \"monthlyPriceCents\": 19900,\n    \"overageRatePerMinute\": 0.10,\n    \"minutesAllowance\": 400\n  }\n}"
    }]
  }
}

get_call_transcript

TOOL

Retrieve metadata for a specific AI voice call by its log ID. Returns duration, direction, and timestamp information.

Input Parameters

ParameterTypeRequiredDescription
callIdstringrequiredCall log UUID

Response Fields

FieldTypeDescription
idstringCall log ID
durationSecondsnumberCall duration in seconds
directionstringCall direction: inbound or outbound
createdAtstringISO 8601 timestamp
Requestjson
{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "get_call_transcript",
    "arguments": {
      "callId": "f7e8d9c0-..."
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "content": [{
      "type": "text",
      "text": "{\n  \"id\": \"f7e8d9c0-..\",\n  \"durationSeconds\": 247,\n  \"direction\": \"inbound\",\n  \"createdAt\": \"2026-04-14T15:30:00Z\"\n}"
    }]
  }
}

get_health

TOOL

Get real-time system health status including database connectivity, response latency, circuit breaker states, and server version. Useful for agents to check service availability before calling other tools.

Input Parameters

ParameterTypeRequiredDescription
No parameters required

Response Fields

FieldTypeDescription
statusstring'healthy' or 'degraded'
timestampstringISO 8601 current server time
dbstring'connected' or 'disconnected'
dbLatencyMsnumberDatabase query latency in ms
circuitsobjectCircuit breaker states per service (if any tripped)
serverobject{ name, version }
Requestjson
{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "tools/call",
  "params": {
    "name": "get_health",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 6,
  "result": {
    "content": [{
      "type": "text",
      "text": "{\n  \"status\": \"healthy\",\n  \"timestamp\": \"2026-04-14T02:30:00Z\",\n  \"db\": \"connected\",\n  \"dbLatencyMs\": 4,\n  \"server\": {\n    \"name\": \"dispatchnode\",\n    \"version\": \"1.0.0\"\n  }\n}"
    }]
  }
}

Error Codes

CodeNameHTTPDescription
-32700Parse Error400Invalid JSON was received. Check your request body formatting.
-32600Invalid Request400The JSON is valid but not a valid JSON-RPC 2.0 request. Must include jsonrpc: '2.0' and a method field.
-32601Method Not Found200The requested method does not exist. Valid methods: initialize, tools/list, tools/call.
-32602Invalid Params200Unknown tool name passed to tools/call, or missing required parameters for a tool.
-32603Internal Error200Server-side error during tool execution (e.g. database timeout, validation failure).
-32001Authentication Error401Missing or invalid auth. Send Authorization: Bearer dnk_... (operator) or X-Org-Slug: <slug> (customer).
-32000Rate Limited429Customer tier rate limit exceeded. 30 requests/min or 10 bookings/hour per IP.
Error Response Examplejson
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32001,
    "message": "Invalid or revoked API key"
  }
}

SDK Examples

The MCP endpoint works with any HTTP client. Here are examples in popular languages:

curl (Customer — no API key)bash
# Customer tier: use X-Org-Slug (found in <link> tag on client site)
curl -X POST https://www.dispatchnode.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "X-Org-Slug: eventrestroomrentals" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "check_availability",
      "arguments": {
        "startDate": "2026-04-15",
        "endDate": "2026-04-16"
      }
    }
  }'
curl (Operator — full access)bash
# Operator tier: use Bearer token for all tools
curl -X POST https://www.dispatchnode.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer dnk_your_api_key_here" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list"
  }'
Pythonpython
import requests

BASE_URL = "https://www.dispatchnode.com/api/mcp"
API_KEY = "dnk_your_api_key_here"

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {API_KEY}"
}

# List available tools
response = requests.post(BASE_URL, json={
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list"
}, headers=headers)

tools = response.json()["result"]["tools"]
print(f"Available tools: {[t['name'] for t in tools]}")

# Book a job
response = requests.post(BASE_URL, json={
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
        "name": "book_job",
        "arguments": {
            "customerName": "Jane Doe",
            "customerPhone": "+15559876543",
            "serviceAddress": "456 Oak Ave, Houston, TX",
            "scheduledStart": "2026-04-16T14:00:00Z"
        }
    }
}, headers=headers)

import json
result = json.loads(response.json()["result"]["content"][0]["text"])
print(f"Job booked: {result['jobId']}")
Node.js / TypeScripttypescript
const BASE_URL = "https://www.dispatchnode.com/api/mcp";
const API_KEY = "dnk_your_api_key_here";

async function mcpCall(method: string, params?: object) {
  const res = await fetch(BASE_URL, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${API_KEY}`,
    },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: Date.now(),
      method,
      params,
    }),
  });
  return res.json();
}

// List tools
const { result } = await mcpCall("tools/list");
console.log("Tools:", result.tools.map((t: any) => t.name));

// Check availability
const avail = await mcpCall("tools/call", {
  name: "check_availability",
  arguments: {
    startDate: "2026-04-15",
    endDate: "2026-04-16",
  },
});
const data = JSON.parse(avail.result.content[0].text);
console.log(`${data.existingBookings} existing bookings`);
Claude Desktop (mcp config)json
{
  "mcpServers": {
    "dispatchnode": {
      "url": "https://www.dispatchnode.com/api/mcp",
      "transport": "streamable-http",
      "headers": {
        "Authorization": "Bearer dnk_your_api_key_here"
      }
    }
  }
}

Discovery

MCP clients can discover the DispatchNode server through two mechanisms:

1. Well-Known Endpoint

Standard RFC 8414 / RFC 9728 discovery at the well-known URL:

GET https://www.dispatchnode.com/.well-known/mcp.json

2. Widget-Injected Link Tag

When the DispatchNode widget is embedded on a client site, it automatically injects a <link> tag into the host page for white-label discovery:

<link rel="mcp-server" href="https://dispatchnode.com/api/mcp" data-org-slug="eventrestroomrentals" data-tools="book_job,check_availability,get_pricing" data-auth="none" data-auth-header="X-Org-Slug: eventrestroomrentals" data-discovery="https://dispatchnode.com/.well-known/mcp.json" />

Rate Limits & Best Practices

LimitValue
Customer: requests/min30 per IP
Customer: bookings/hour10 per IP
Operator: requests/minUnlimited
Request body size1 MB
Max results (list_jobs)100 per page
Timeout30 seconds

Best Practices

Call get_health before a batch of operations to verify the system is healthy.
Use check_availability before book_job to avoid scheduling conflicts.
Always check for error responses — tool calls return errors in the JSON-RPC error field, not HTTP status codes.
Use monotonically increasing IDs for JSON-RPC request tracking.
Store the API key securely — never in client-side code or public repos.
Each API key is scoped to one org. Use separate keys per environment (dev/staging/prod).

© 2026 DispatchNode