# TaskBullet Agent API and Remote MCP

Authenticated VA handoff for AI agents (Grok Bot, Cursor, cloud MCP clients).
This is NOT the public site MCP at https://taskbullet.com/api/mcp.

- HTML docs: https://taskbullet.com/docs/agent-api
- Markdown: https://taskbullet.com/docs/agent-api.md
- Keys: https://taskbullet.com/dashboard/settings/api-keys

## Remote MCP

- URL: https://taskbullet.com/api/agent-mcp
- Transport: streamable HTTP (JSON-RPC)
- Auth: header `x-api-key: tb_live_…` (Authorization: Bearer tb_live_… also accepted). API key only — not OAuth. Plugin variable `TASKBULLET_API_KEY`. Call `get_balance` before proposing spend. Confirm with the user before `delegate_task` (real hours) unless they already said to send it.
- Discovery: https://taskbullet.com/.well-known/mcp.json (entry `taskbullet-agent`)
- Unauthenticated GET returns name/version/docs and `auth.required: true`. Tools stay locked. OAuth well-known probes return JSON `oauth_not_supported` (not HTML).

### Tools

- `get_balance` — GET /api/v1/balance. Remaining hours, canDelegate, addHoursUrl. No args. Call this first.
- `delegate_task` — POST /api/v1/delegate. Call get_balance first. Args: title (required, max 5000), description, priority (low|normal|high|urgent), dueDate, sourceAgent, webhookUrl.
- `list_tasks` — GET /api/v1/tasks. Args: status (pending|in_progress|completed|failed|all). Each row includes title and a short result on completed tasks.
- `get_task` — GET /api/v1/tasks/{taskId}. Args: taskId. Full result.

When the AI cannot finish (phone, 2FA, captcha, physical world, subjective QA, long manual work), call get_balance, confirm spend, then delegate_task. Poll get_task or pass webhookUrl. Never invent VA results.

### Grok Bot

Settings → Plugins → custom MCP (or TaskBullet when listed). Server URL https://taskbullet.com/api/agent-mcp. Paste the API key into connector auth. If an OAuth connect card appears, dismiss it — this server is API-key only.

### Cursor / Grok Build (TOML)

```toml
[mcp_servers.taskbullet_agent]
url = "https://taskbullet.com/api/agent-mcp"
headers = { "x-api-key" = "tb_live_YOUR_KEY" }
enabled = true
```

### Cursor / Claude mcp.json (JSON)

```json
{
  "mcpServers": {
    "taskbullet-agent": {
      "url": "https://taskbullet.com/api/agent-mcp",
      "headers": { "x-api-key": "tb_live_YOUR_KEY" }
    }
  }
}
```

Local stdio (`npx @taskbullet/mcp-server`) is laptop-only. Cloud Grok Bots cannot use npx.

## REST Agent API

Base: https://taskbullet.com
Auth: x-api-key: tb_live_…
Rate limit: 60 req / min / key

### POST /api/v1/delegate

Body: task or title (required), context or description, priority (low|normal|high|urgent), dueDate, webhookUrl, sourceAgent.

200: { success, taskId, status: "received", message }
402: { error, hoursRemaining, addHoursUrl } — no hour balance
409: account not provisioned (complete onboarding)
401: missing/invalid key

### GET /api/v1/balance

200: { hoursRemaining, canDelegate, addHoursUrl }. Auth required. No other account fields.

### GET /api/v1/tasks

Query: status=pending|in_progress|completed|failed|all (default all). Up to 50 tasks. Each item: taskId, title, status, priority, createdAt, completedAt?, result? (short snippet when completed).

### GET /api/v1/tasks/{taskId}

Poll until status is completed or failed. Completed responses include result.

Statuses: pending (queued), in_progress (in Basecamp), completed (VA done), failed.

## Webhooks

If webhookUrl is set on delegate, TaskBullet POSTs a signed payload when the VA completes:

Headers: x-taskbullet-signature (hex HMAC-SHA256 of `${unixSeconds}.${rawBody}`), x-taskbullet-timestamp (unix seconds).
Event: task.completed with taskId, taskTitle, status, result.

webhookUrl must be a public https URL. Retries up to 5 times.

## Errors

| Status | Cause |
| 400 | Invalid body |
| 401 | Missing, invalid, or revoked API key |
| 402 | No hour balance |
| 409 | Account not provisioned |
| 429 | Rate limit — honor Retry-After |

Hours are gated at 402; VA time deducts from the bucket when work is tracked, not as a prepaid debit on submit.
