MCP Server

Doorstep is an MCP server that gives your AI agent the ability to do real things in the physical world. Connect it to any MCP-compatible client — Claude, GPT, or your own agent — and your agent gets tools to create tasks, approve quotes, and track progress. Currently serving San Francisco only.

Protocol

MCP (Streamable HTTP)

Auth

OAuth or API key

Billing

Card on file, charged per task

Setup

Add Doorstep to any MCP-compatible client. All clients connect via OAuth — your account is created automatically the first time you log in.

MCP Server URL

https://trydoorstep.app/mcp

Claude

Paste this into your agent:

Claude Desktop

Add this to your Claude Desktop MCP settings:

claude_desktop_config.json
{
  "mcpServers": {
    "doorstep": {
      "url": "https://trydoorstep.app/mcp"
    }
  }
}

Cursor

Add this to .cursor/mcp.json in your project or ~/.cursor/mcp.json globally:

.cursor/mcp.json
{
  "mcpServers": {
    "doorstep": {
      "url": "https://trydoorstep.app/mcp"
    }
  }
}

Restart Cursor after saving. OAuth triggers on first use.

Windsurf

Add this to ~/.codeium/windsurf/mcp_config.json:

mcp_config.json
{
  "mcpServers": {
    "doorstep": {
      "url": "https://trydoorstep.app/mcp"
    }
  }
}

VS Code / Copilot

Add this to your VS Code MCP settings (Command Palette → “MCP: Edit Raw Configuration”):

mcp.json
{
  "servers": {
    "doorstep": {
      "url": "https://trydoorstep.app/mcp"
    }
  }
}

Codex CLI

Paste this into your agent:

Gemini CLI

Paste this into your agent:

OpenClaw

First, generate an API key from your dashboard. Then add the Doorstep MCP server to your openclaw.json:

openclaw.json
{
  "mcpServers": {
    "doorstep": {
      "command": "npx",
      "args": ["-y", "doorstep"],
      "env": {
        "DOORSTEP_API_KEY": "${DOORSTEP_API_KEY}"
      }
    }
  }
}

OpenClaw uses a local stdio bridge and requires an API key. You can also install directly from ClawHub.

Other MCP Clients

Any MCP client that supports HTTP transport can connect to Doorstep. Point it at the server URL and authenticate via OAuth or Bearer token:

https://trydoorstep.app/mcp

If your client uses a JSON config file, add {"mcpServers":{"doorstep":{"url":"https://trydoorstep.app/mcp"}}}. OAuth triggers automatically on first use.

API Key (alternative)

If your client does not support OAuth, you can authenticate with a Doorstep API key instead.Generate one from your dashboard and pass it as a Bearer token:

Authorization: Bearer doorstep_sk_...

First time? When you connect via OAuth, your account is created automatically. Before you can create tasks, you need to add a credit card. Use the get_accounttool to check your billing status — it will include a link to add your card if needed.

Billing

Doorstep requires a credit card on file before you can create tasks. You are charged per task, and only when you explicitly approve a quote.

Card required upfront

Add a credit card before creating your first task. The do tool will give you a link if you haven't set one up yet.

No charge without approval

Every task goes through a quote step. Your card is only charged when you call approve_task. You always see the price before committing.

Flat task fees

Every task costs a flat $5, $10, or $20 based on complexity. Pass-through costs (purchases, supplies) are billed at cost on top. The quoted total includes everything.

Tools

do

Create a new task. Describe what you need in plain language and Doorstep will research it, build a plan, and present a quote for approval. A credit card must be on file.

Parameters

ParameterTypeRequiredDescription
inputstringRequiredNatural-language description of what you need done in the real world.
contextobjectOptionalOptional structured context — addresses, preferences, constraints, or any relevant data.
max_budgetnumberOptionalMaximum budget in USD. The quote must come in at or under this amount.
scheduled_forstring (ISO 8601)OptionalSchedule dispatch for a future time (e.g. "2026-04-01T09:00:00-07:00"). Must fall within service hours (Mon–Fri 8 AM – 5 PM PT). If omitted and submitted after hours, dispatch is auto-scheduled for the next window.
callback_urlstring (url)OptionalWebhook URL to receive task updates. A signing secret is returned in the response.

Example

MCP Tool Call
use_mcp_tool doorstep do

{
  "input": "Drop off a dozen donuts at the Figma office in SF tomorrow morning",
  "context": {
    "address": "760 Market St, San Francisco, CA 94102",
    "preferred_shop": "Bob's Donuts"
  },
  "max_budget": 100
}

Response

The tool waits up to 2 minutes for the quote. If the quote is ready, the response includes the plan and pricing. Otherwise, it returns a task ID to check later with get_task.

{
  "id": "7f8e9d0c-...",
  "status": "quoted",
  "plan": {
    "steps": [
      "Pick up one dozen assorted donuts from Bob's Donuts",
      "Drive to 760 Market St, San Francisco",
      "Deliver to Figma office with handwritten note"
    ],
    "estimated_minutes_min": 30,
    "estimated_minutes_max": 60
  },
  "tier_cents": 2000,
  "estimated_total_cents": 5600,
  "message": "Quote ready. Review the plan and pricing, then approve, request changes, or decline."
}
list_tasks

List your tasks, newest first. Optionally filter by status. Returns a summary of each task. Use get_task for full details on a specific task.

Parameters

ParameterTypeRequiredDescription
statusstringOptionalFilter by task status (received, researching, needs_info, quoted, payment_pending, approved, in_progress, completed, failed, cancelled).
limitnumberOptionalMaximum number of tasks to return (default 20, max 50).

Response

{
  "tasks": [
    {
      "id": "7f8e9d0c-...",
      "status": "completed",
      "input": "Drop off a dozen donuts at the Figma office...",
      "created_at": "2026-03-27T10:00:00Z",
      "updated_at": "2026-03-27T12:30:00Z",
      "estimated_total_cents": 5600
    },
    {
      "id": "a1b2c3d4-...",
      "status": "in_progress",
      "input": "Pick up dry cleaning from Valencia St...",
      "created_at": "2026-03-28T09:00:00Z",
      "updated_at": "2026-03-28T09:45:00Z"
    }
  ],
  "count": 2
}
get_task

Check the status of a task, including any pending follow-up questions. When status is "quoted", the response includes the plan and price awaiting your approval.

Parameters

ParameterTypeRequiredDescription
task_idstring (uuid)RequiredThe task ID returned when you created the task.

Response

{
  "id": "7f8e9d0c-...",
  "status": "completed",
  "input": "Drop off a dozen donuts at the Figma office...",
  "plan": { ... },
  "resolution": "Delivered 12 assorted donuts from Bob's. Front desk signed.",
  "estimated_total_cents": 5600
}
approve_task

Approve a quoted task and authorize payment. Your card on file is charged the quoted amount. No charge is made until you explicitly call this tool.

Parameters

ParameterTypeRequiredDescription
task_idstring (uuid)RequiredThe task ID to approve.

Response

{
  "id": "7f8e9d0c-...",
  "status": "in_progress",
  "estimated_total_cents": 5600,
  "approved_at": "2026-03-27T12:30:00Z",
  "message": "Task approved. $56.00 has been charged to your card on file."
}
respond_to_task

Answer a follow-up question from the Doorstep team. Tasks move to 'needs_info' when we need clarification before proceeding.

Parameters

ParameterTypeRequiredDescription
task_idstring (uuid)RequiredThe task ID to respond to.
responsestringRequiredYour answer to the follow-up question.

Example

MCP Tool Call
use_mcp_tool doorstep respond_to_task

{
  "task_id": "7f8e9d0c-...",
  "response": "Yes, glazed donuts are fine. No nuts please."
}
revise_quote

Request changes to a quoted task. Provide feedback and the task will be re-researched with a new quote generated.

Parameters

ParameterTypeRequiredDescription
task_idstring (uuid)RequiredThe task ID to revise.
feedbackstringRequiredWhat you want changed (e.g. "Keep the total under $70" or "Use a different shop").
cancel_task

Cancel a task. Before payment, cancellation is free. After payment but before the doer starts, a full refund is issued. If the doer is actively working, cancellation requires force: true and no refund is issued.

Parameters

ParameterTypeRequiredDescription
task_idstring (uuid)RequiredThe task ID to cancel.
forcebooleanOptionalSet to true to confirm cancellation of an in-progress task with an active doer (no refund will be issued).

Response

{
  "id": "7f8e9d0c-...",
  "status": "cancelled",
  "refunded": true,
  "message": "Task cancelled. A full refund has been issued to your card on file."
}
rate_task

Leave a rating for a completed task. Only works on tasks with status "completed". One rating per task.

Parameters

ParameterTypeRequiredDescription
task_idstring (uuid)RequiredThe UUID of the completed task.
ratinginteger (1-5)RequiredStar rating from 1 (poor) to 5 (excellent).
commentstringOptionalOptional text feedback about the task experience.

Response

{
  "review_id": "r1a2b3c4-...",
  "task_id": "7f8e9d0c-...",
  "rating": 5,
  "comment": "Fast and careful delivery. Great communication.",
  "message": "Review submitted. Thank you for your feedback!"
}
get_receipt

Get a cost breakdown for a task. Returns estimated costs (from the quote) and actual costs (from the doer’s final bill, if submitted). Useful after task completion to see what was charged.

Parameters

ParameterTypeRequiredDescription
task_idstring (uuid)RequiredThe task ID to get the receipt for.

Response

{
  "task_id": "7f8e9d0c-...",
  "status": "completed",
  "quote": {
    "task_fee_cents": 2000,
    "pass_through_cents": 3600,
    "total_cents": 5600
  },
  "final": {
    "task_fee_cents": 2000,
    "pass_through_cents": 3200,
    "total_cents": 5200,
    "amount_charged_cents": 5600,
    "refund_cents": 400
  },
  "line_items": [
    { "description": "Assorted donuts from Bob's", "amount_cents": 3200 }
  ],
  "message": "Receipt with quote and final costs."
}
get_messages

Retrieve the message thread for a task. Messages include doer questions, your replies, and system notes. Use this to check if the doer has asked a question or posted a status update.

Parameters

ParameterTypeRequiredDescription
task_idstring (uuid)RequiredThe task ID to retrieve messages for.

Response

{
  "task_id": "7f8e9d0c-...",
  "status": "in_progress",
  "messages": [
    {
      "id": "a1b2c3d4-...",
      "sender_type": "doer",
      "body": "I'm at the shop — they have red, white, and pink roses. Which do you prefer?",
      "created_at": "2026-03-27T14:22:00Z"
    },
    {
      "id": "e5f6g7h8-...",
      "sender_type": "client",
      "body": "Red roses please.",
      "created_at": "2026-03-27T14:25:00Z"
    }
  ],
  "message_count": 2
}
send_message

Send a message to the doer working on your task. Use this to answer doer questions, provide clarifications, or give additional instructions. The message is relayed to the doer via Telegram.

Parameters

ParameterTypeRequiredDescription
task_idstring (uuid)RequiredThe task ID to send a message for.
messagestringRequiredThe message to send to the doer.
image_urlstring (url)OptionalOptional image URL to attach. The image will be persisted and delivered to the doer.

Example

MCP Tool Call
use_mcp_tool doorstep send_message

{
  "task_id": "7f8e9d0c-...",
  "message": "Red roses please. A dozen."
}

Response

{
  "task_id": "7f8e9d0c-...",
  "status": "in_progress",
  "message_count": 3,
  "message": "Message sent."
}
wait_for_update

Block until something changes on a task — a status transition, a new doer message, or task completion. Returns the event that occurred. Call this in a loop after approving a task to stay informed without manual polling.

Parameters

ParameterTypeRequiredDescription
task_idstring (uuid)RequiredThe task ID to watch for updates.
timeoutnumberOptionalHow long to wait in seconds (default 120, max 300). Returns "no_change" if nothing happens before the timeout.

Events

task.quotedQuote is ready — plan and pricing available for approval.
task.status_changedTask status changed (e.g. approved, in_progress, assigned).
task.messageThe doer sent a message. Review and respond via send_message.
task.completedTask is complete. Resolution details included.
no_changeNothing happened before the timeout. Call wait_for_update again.

Response

{
  "task_id": "7f8e9d0c-...",
  "event": "task.message",
  "status": "in_progress",
  "message_from": "doer",
  "message_body": "I'm at the shop — they have red, white, and pink roses. Which do you prefer?",
  "message": "New message from doer. Review and respond if needed via send_message."
}

Account

register

Create a new Doorstep account and get an API key. No prior authentication required. The user gets a full account they can also log into at trydoorstep.app.

Parameters

ParameterTypeRequiredDescription
emailstringRequiredEmail address for the account.
passwordstringRequiredPassword for the account (min 8 characters).
namestringOptionalDisplay name for the account.

Response

{
  "api_key": "doorstep_sk_...",
  "user_id": "u1a2b3c4-...",
  "message": "Account created. Use this API key as a Bearer token...",
  "billing_url": "https://trydoorstep.app/billing"
}
get_account

Check your account status, including whether billing is set up. Returns a billing URL if you need to add a credit card.

Parameters

No parameters required.

Response

{
  "name": "Sarah Chen",
  "email": "sarah@example.com",
  "has_payment_method": false,
  "billing_url": "https://trydoorstep.app/billing",
  "message": "No credit card on file. Add one at the billing URL before creating tasks."
}
get_settings

Get the current account settings, including emergency contact info and spending limits.

Parameters

No parameters required.

Response

{
  "monthly_spending_limit": 500,
  "phone": "***1234",
  "fallback_confirmed": true
}
update_settings

Update account settings. Only provided fields are changed; omitted fields keep their current values.

Parameters

ParameterTypeRequiredDescription
monthly_spending_limitnumber | nullOptionalMaximum total spend per calendar month in USD. Set to null to remove the limit.
phonestringOptionalEmergency contact phone number. Doers will use this to reach you if your agent is offline during a task.

Example

MCP Tool Call
use_mcp_tool doorstep update_settings

{
  "monthly_spending_limit": 200,
  "phone": "+14155551234"
}

Task Lifecycle

Every task follows this flow. Most tasks move from received to quoted within minutes. Real-world execution (in_progress to completed) depends on the errand.

Received

Task created. Doorstep is researching your request and building a plan.

Researching

Actively gathering info — checking availability, pricing, logistics.

Needs Info

We have a follow-up question. Use respond_to_task to answer.

Quoted

Plan and price quote are ready. Use approve_task to greenlight and authorize payment.

Payment Pending

You approved the quote but payment has not been collected yet. If your card was declined, update your payment method and call approve_task again to retry.

Approved

You approved the quote and payment was charged. A tasker is being assigned.

Scheduled

Task approved and paid. Dispatch is scheduled for a future service window. Use wait_for_update to receive a notification when dispatch occurs.

In Progress

A tasker is actively working on your request.

Completed

Task finished successfully. Resolution details available via get_task.

Failed

Something went wrong. We'll reach out to resolve it.

Cancelled

Task was cancelled before completion.

Getting Results Back

Real-world tasks take time — minutes to hours. Here’s how results flow back to your agent.

Within the session (quoting phase)

When you call do, Doorstep waits up to 2 minutes for the quote to be ready. Most quotes come back in under a minute, so you get the plan and pricing in the same tool response. If it takes longer, you get a task ID to check later.

Across sessions (execution phase)

Once a task is approved and a doer is working on it, execution can take hours. Your MCP session may end in the meantime. To check results later, just call get_taskwith the task ID in a new session. Ask your agent “What happened with my cake delivery?” and it will call get_task to get the latest status and resolution.

Doer communication (messaging)

While a task is in progress, the doer may have questions — “They have three options, which do you want?” Use get_messages to check for doer messages and send_messageto reply. This works in any MCP client — including Cursor, Claude Code, and other tools that can’t receive webhooks.

Webhooks (for agent platforms)

If your agent platform has its own server endpoint, pass a callback_urlwhen creating a task. Doorstep will POST status updates to that URL as they happen — no polling needed. See below.

Webhooks

When you provide a callback_urlon task creation, Doorstep sends POST requests to that URL whenever something happens — a quote is ready, a doer asks a question, or the status changes.

Events

ParameterTypeRequiredDescription
task.quotedeventOptionalQuote is ready — plan and pricing are available for approval.
task.messageeventOptionalThe doer sent a message or asked a question about the task.
task.status_changedeventOptionalTask status changed (approved, in_progress, assigned, etc.).
task.completedeventOptionalTask finished — resolution details included.

Payload

{
  "event": "task.completed",
  "task_id": "7f8e9d0c-...",
  "timestamp": "2026-03-27T16:30:00Z",
  "task": {
    "id": "7f8e9d0c-...",
    "status": "completed",
    "input": "Drop off a dozen donuts at the Figma office...",
    "resolution": "Delivered 12 assorted donuts from Bob's. Front desk signed.",
    "estimated_total_cents": 5600
  }
}

Verifying signatures

Every webhook includes an X-Doorstep-Signature header. Verify it by computing an HMAC-SHA256 of the raw request body using the callback_secret returned at task creation.

Node.js
import { createHmac } from 'crypto';

function verify(body, secret, signature) {
  const expected = 'sha256=' +
    createHmac('sha256', secret).update(body).digest('hex');
  return expected === signature;
}

Doorstep retries failed deliveries up to 3 times with exponential backoff. Your endpoint should return a 2xx status to acknowledge receipt. If all retries fail, the event is dropped — you can always fall back to polling with get_task.