TaskBullet

io.github.GriffMurder由 GitHub 帳號 GriffMurder 發布v0.2.1更新於 Oct 29, 2026

Place US/CA phone calls and delegate tasks an AI agent cannot finish.

已驗證Streamable HTTP可網頁執行效率與工作流溝通與協作

概覽

AI 產生的概覽

TaskBullet 讓助理把無法獨立完成的工作交給真人虛擬助理,或代撥美國/加拿大真人電話,並取回結果。

可以做什麼
  • 查詢餘額:讀取剩餘 VA 時數與通話錢包餘額,含未結算的預扣
  • 委派任務:提交任務簡報給真人虛擬助理,列出近期任務、查看狀態與結果,並確認、取消或退回交付
  • 撥打電話:驗證通話內容與預扣金額,代撥一通真人電話,查看或補齊資訊、取消通話,並讀取助理的通話總結
  • 追蹤完成:輪詢任務與通話狀態,或透過 webhook 與回呼接收通知
適用情境
當代理遇到自己無法完成的工作時適用,例如打電話、兩步驟驗證或驗證碼步驟、線下事務、主觀品管或長時間人工作業,且使用者願意為人工服務付費。也適合需要向美國或加拿大商家實際外撥的流程。
執行需求
需要 TaskBullet 帳號與 API 金鑰(tb_live_...),透過 TASKBULLET_API_KEY 環境變數或 x-api-key 標頭提供,金鑰在後台建立且只顯示一次。可用 Node.js 透過 npx 在本機執行,也可連線託管的遠端端點。委派任務需預付 VA 時數,電話需通話錢包有餘額,並需能存取 TaskBullet API。
安裝前請注意
會產生實際費用:委派任務依記錄的 VA 工時計費(15 分鐘取整,受 maxHours 上限限制),電話從通話錢包扣款,第一分鐘 2.50 美元、之後每分鐘 1 美元,預設 5 分鐘通話約預扣 6.50 美元。confirm_task、cancel_task、reopen_task、place_call 與 cancel_call 會改變實際工作與費用,伺服器要求先經人工確認。切勿在簡報或通話中填入密碼、一次性驗證碼、復原金鑰、Cookie 或 API 金鑰。僅支援美國與加拿大號碼,且不提供錄音。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 TaskBullet,將其新增到工作區。
  2. 連接 x-api-key 憑證。它們會被私密儲存,絕不會在公開頁面上展示。
  3. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.GriffMurder%2Ftaskbullet/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "taskbullet": {
      "type": "http",
      "url": "https://taskbullet.com/api/agent-mcp",
      "headers": {
        "x-api-key": "<YOUR_API_KEY>"
      }
    }
  }
}

README

Your AI agent can place a real phone call.

A person dials the number. Your agent gets the answers back. The server is @taskbullet/mcp-server.

[npm version] [MIT License]

Pricing

$2.50 for the first minute, then $1 per additional minute. The charge comes from the calls wallet, not from prepaid VA hours. US and Canada numbers only. Recording is not available. A system failure that never dials is fully refunded.

get_balance shows balance_cents (spendable after open holds), holds_cents, and wallet_cents. The default max_minutes is 5. At the rate above, five minutes is $6.50. validate_call returns hold_cents for the body you are about to send, and it places no hold. Use hold_cents.

HTTP 402 payment_required means the wallet cannot cover the hold. Add funds at addFundsUrl. That read does not create a Stripe session. Calls are pay-as-you-go. There is no trial.

Example prompts

Copy one of these into the agent after the server is installed. Put the real US or Canada number in the prompt. Do not put a password, a one-time code, or the API key in it.

Book an appointment:

text
Call the dentist and book me the earliest appointment next Tuesday after 1pm. The office is Bright Smile Dental at (801) 555-0148. Ask which times they have, book one, and bring back the time and any confirmation number. Confirm the hold with me before you place the call. Do not record it.

Call a vendor to check an order:

text
Call Northwind Supply at (415) 555-0199 and check order NW-10442. Ask whether it shipped, the carrier, and the tracking number. Confirm the hold with me before you place the call. US number, no recording.

Confirm a reservation:

text
Call Harbor Grill at (206) 555-0177 and confirm the reservation for Alex Chen, party of 4, this Friday at 7:00pm. Ask them to say the name, time, and party size back. Confirm the hold with me before you place the call. Do not record it.

Install

Create a key at taskbullet.com/dashboard/settings/api-keys. It is shown once. The buttons below install a placeholder tb_live_your_key_here. Replace that placeholder in the client config before the first call. Do not paste the real key into chat.

The config runs npx -y @taskbullet/mcp-server on your machine. Cloud agents that cannot run npx should use the hosted URL in Cursor and cloud agents.

Cursor

[Install in Cursor] [Install in Cursor (light)]

GitHub does not open cursor:// links. Copy this into a browser:

text
cursor://anysphere.cursor-deeplink/mcp/install?name=taskbullet&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkB0YXNrYnVsbGV0L21jcC1zZXJ2ZXIiXSwiZW52Ijp7IlRBU0tCVUxMRVRfQVBJX0tFWSI6InRiX2xpdmVfeW91cl9rZXlfaGVyZSJ9fQ==

Decoded config:

json
{  "command": "npx",  "args": ["-y", "@taskbullet/mcp-server"],  "env": {    "TASKBULLET_API_KEY": "tb_live_your_key_here"  }}

VS Code

[Install in VS Code]

[Install in VS Code Insiders]

vscode:mcp/install? and vscode-insiders:mcp/install? carry the same URL-encoded JSON. The name is inside that JSON:

json
{"name":"taskbullet","command":"npx","args":["-y","@taskbullet/mcp-server"],"env":{"TASKBULLET_API_KEY":"tb_live_your_key_here"}}

Claude Code

bash
claude mcp add taskbullet --env TASKBULLET_API_KEY=tb_live_your_key_here -- npx -y @taskbullet/mcp-server

Replace tb_live_your_key_here before you run it. From a marketplace, after this repo is on the default branch:

text
/plugin marketplace add GriffMurder/taskbullet-mcp-server

Then install taskbullet@taskbullet. The plugin prompts for the key. It does not read a key out of the shell.

JSON

Claude Desktop and any other stdio client:

json
{  "mcpServers": {    "taskbullet": {      "command": "npx",      "args": ["-y", "@taskbullet/mcp-server"],      "env": {        "TASKBULLET_API_KEY": "tb_live_your_key_here"      }    }  }}

claude_desktop_config.json locations are in the MCP quickstart. Restart the app after you save the file.

Tools

Names, arguments, and limits below match the code in src/server.ts.

ToolCallsNotes
get_balanceGET /api/v1/balanceRead-only. Hours and the calls wallet. Call this before proposing spend.
delegate_taskPOST /api/v1/delegateFiles a brief. Idempotency-Key required. Spends real hours after the customer starts it on Work.
list_tasksGET /api/v1/tasksRead-only. Up to 50 tasks. Filter includes cancelled.
get_taskGET /api/v1/tasks/{taskId}Read-only. Stop on completed, failed, or cancelled. awaitingCustomerConfirm means ask the human.
confirm_taskPOST /api/v1/tasks/{taskId}/confirmAccepts a delivery and settles tracked hours. Idempotency-Key required. Ask the human first.
cancel_taskPOST /api/v1/tasks/{taskId}/cancelReleases the hold and bills only tracked time. Idempotency-Key required. Ask the human first.
reopen_taskPOST /api/v1/tasks/{taskId}/reopenSends the delivery back. reason required. Idempotency-Key required. Ask the human first.
place_callPOST /api/v1/callsOne human call. US and Canada only. record_call must be false or omitted. Idempotency-Key required.
validate_callPOST /api/v1/calls/validateChecks the body. Creates nothing and places no hold. Returns hold_cents.
get_callGET /api/v1/calls/{id}Read-only. Includes needs_info or the final result.
update_callPATCH /api/v1/calls/{id}Fills missing fields while the call is needs_info.
cancel_callPOST /api/v1/calls/{id}/cancelAsks ops to cancel. Stays cancel_pending until ops confirms. A confirm before any dial refunds the hold. After the dial starts, the error is cancel_too_late and the call bills normally.
get_transcriptGET /api/v1/calls/{id}/transcript.txtVA wrap-up summary, not a recording. source is wrap_up_summary and recorded is false. Empty is transcript_not_ready. No dial is no transcript: call not placed. Cancel after the dial started is call_cancelled.

delegate_task arguments: title (required, max 5000), description (max 8000), priority (low | normal | high | urgent, default normal), dueDate, sourceAgent, webhookUrl (https), maxHours (default 0.5, max 8), idempotencyKey (required). The same value is sent as the Idempotency-Key header and is not put in the JSON body. A repeat returns the original task.

A tb_live_ key files the brief. The customer starts VA hours on Work. awaiting_customer_start means the job has not started. Do not say the assistant has started. Poll get_task until completed, failed, or cancelled, or pass webhookUrl. When get_task shows awaitingCustomerConfirm, ask the human, then confirm_task, cancel_task, or reopen_task. Do not confirm, cancel, or reopen without the human. Customer cancel is cancelled and does not send the completion webhook. If nobody confirms, an agent-created task confirms itself after 3 days.

maxHours is a spend cap. Tracked time is what is billed (15-minute rounding). HTTP 402 means a live read is not above zero. Buy hours at the addHoursUrl (the packages page, not a new trial). HTTP 422 means the cap does not fit open caps: hours remain, lower maxHours to capRoom or wait. HTTP 503 means hours were unavailable. That is not a buy-hours error.

Never put passwords, OTP codes, recovery keys, cookies, or API keys in a brief or a call. The server drops those locally and the API rejects them.

Human phone calls use place_call, not delegate_task. Required fields are phone, business_name, purpose (info, scheduling, account_servicing, or vendor_ops), goal (max 4000), questions (1 to 20 items of {id, ask, type?}, id max 80, ask max 1000), on_behalf_of, deadline (ISO-8601), consent_attestation (true), and idempotencyKey. max_attempts defaults to 3 and maxes at 5. max_minutes defaults to 5 and maxes at 60. language is en, fil, tl, war, or ceb.

Only US and Canada numbers can be placed. record_call must be false or omitted. True is rejected locally and nothing is sent. The hold is the full call: the first minute is the tier minimum, then the per-minute rate. A tier 1 call at the default 5 minutes holds $6.50. validate_call is the same body without idempotencyKey, and its hold_cents is the figure to trust. valid stays true when the wallet is short. warnings then include insufficient_balance. place_call is pay-as-you-go from the calls wallet. Poll get_call, or pass an https callback_url. A call outside weekday 09:00–17:00 in the recipient's time zone needs allow_outside_business_hours: true after the customer confirms. The deadline then needs 60 minutes of clock time.

update_call takes call_id plus any of the same body fields. get_call, cancel_call, and get_transcript take call_id.

TaskBullet Hub

TaskBullet Hub is one MCP connection for agents, with human backup.

There are two servers:

ServerURLAuthWhat it can do
Agent (this package, and the hosted remote)https://taskbullet.com/api/agent-mcpx-api-key: tb_live_…get_balance, delegate_task, list_tasks, get_task, confirm_task, cancel_task, reopen_task, place_call, validate_call, get_call, update_call, cancel_call, get_transcript
Public site guidehttps://taskbullet.com/api/mcpnoneRead-only marketing info: services, pricing, hire vs job-seeker routing

The public site server does not see customer accounts, emails, work history, or internal docs. Task delegation is only on the agent server.

Cursor and cloud agents

Cloud agents (Cursor cloud, Grok, hosted Claude) should use the hosted agent URL. They cannot run npx.

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

OpenClaw

The lobster cannot create the account or mint a key. Tell the human, in order:

  1. No account → https://taskbullet.com/get-started?source=openclaw (10 hours, no card)
  2. Issue tb_live_… at https://taskbullet.com/dashboard/settings/api-keys (shown once)
  3. Paste it into the Gateway env TASKBULLET_API_KEY and point Agent MCP at https://taskbullet.com/api/agent-mcp with header x-api-key. Restart. Never put the key in chat.

Install the skill with openclaw skills install @griffmurder/taskbullet. A single human phone call is place_call on the calls wallet. Other unfinished work is get_balance, confirm spend, then delegate_task. No key → the trial URL above. A keyed HTTP 402 on hours is the packages page, not a second trial. A keyed HTTP 402 on a call is add funds, not a trial.

A local Gateway can also launch this package over stdio (npx -y @taskbullet/mcp-server) with TASKBULLET_API_KEY in the environment.

Public site guide (no key)

Read-only. Safe to add beside the agent server.

json
{  "mcpServers": {    "taskbullet-site": {      "url": "https://taskbullet.com/api/mcp"    }  }}

Call understand_site, then match_intent. Job seekers are not hire conversions.

Local streamable HTTP

Stdio is the default. --http serves streamable HTTP on loopback:

bash
export TASKBULLET_API_KEY="tb_live_your_key_here"npx -y @taskbullet/mcp-server --http

Endpoint: http://127.0.0.1:3000/mcp. The key stays in this process. Clients on that machine do not send it.

The process binds to 127.0.0.1 only. It checks Host and Origin so a browser page cannot use DNS rebinding to spend the key. Listening on any other address requires TASKBULLET_HTTP_TOKEN. Send that token as Authorization: Bearer …. It is not the TaskBullet API key.

There is no server-initiated SSE stream. GET returns 405. Responses are JSON. Requests are limited to 60 per minute per client address, and upstream calls follow the Agent API ceiling of 60 per minute. Bodies over 32 KiB are rejected.

Plugins

Cursor: plugins/taskbullet bundles this MCP server, rules/delegate-call-or-task.mdc, and skills/place-call-or-delegate/SKILL.md. Those tell the agent when to use place_call and when to use delegate_task. The repo marketplace is .cursor-plugin/marketplace.json. Submission to the Cursor Marketplace is still manual at cursor.com/marketplace/publish.

Claude Code: .claude-plugin/marketplace.json lists the same plugin. Users add it with /plugin marketplace add GriffMurder/taskbullet-mcp-server. Claude Code loads the skill. It does not load the Cursor rule. Claude starts the vendored server with node and ${CLAUDE_PLUGIN_ROOT}/server/index.js. The prompt supplies the API key and the local HTTP token, and the vendored server reads only those values. Cursor keeps using npx.

Environment

VariableRequiredDefaultPurpose
TASKBULLET_API_KEYyes—tb_live_… key. npm and Cursor read it from the environment. The Claude plugin reads the prompt value only. Never logged or copied into tool results.
TASKBULLET_API_BASEnohttps://taskbullet.com/api/v1Override for staging
TASKBULLET_SOURCE_AGENTnomcp-clientAudit label stored on each brief
TASKBULLET_TRANSPORTnostdioSet to http to serve streamable HTTP
TASKBULLET_HTTP_HOSTno127.0.0.1Bind address. Non-loopback requires a token
TASKBULLET_HTTP_PORTno3000HTTP port
TASKBULLET_HTTP_TOKENwhen exposed—Local HTTP auth for npm and Cursor. The Claude plugin reads the prompt value only. Not the TaskBullet API key
TASKBULLET_HTTP_ALLOWED_ORIGINSnoloopback originsExtra browser Origin values, comma-separated

Completion

  1. Poll get_task until status is completed, failed, or cancelled. When awaitingCustomerConfirm is true, ask the human, then confirm_task, cancel_task, or reopen_task.
  2. Webhook — pass an https webhookUrl. TaskBullet POSTs a signed body when the customer closes the job, and task.awaiting_confirmation when a delivery is waiting. A customer cancel does not send task.completed. See the webhook docs.
  3. Calls — poll get_call until the call finishes, or pass an https callback_url. Read get_transcript when the call has a transcript.

delegate_task, confirm_task, cancel_task, reopen_task, and place_call require idempotencyKey. The package sends that value as the Idempotency-Key header and does not put it in the JSON body. The same account and key returns the original result.

How TaskBullet bills hours

  • Hours are prepaid buckets. They roll over for 90 days.
  • Delegated tasks route to the virtual assistant on the account.
  • The API call is free. Hours deduct when work is tracked, not when the brief is filed.
  • Phone calls do not spend those hours. They spend the calls wallet.

Docs: agent API · OpenAPI · site

Registry

mcpName in this release is io.github.GriffMurder/taskbullet. That is the live registry listing. Publishing 0.2.1 updates it. The preferred name com.taskbullet/mcp needs a DNS TXT record or an HTTP proof on taskbullet.com. That proof is not published yet, so this package does not switch names. Commands, the TXT record, and the directory submissions are in PUBLISHING.md.

License

MIT — see LICENSE.

來源:README.md,提交 e6ee71b

工具

13

get_balance

Get balance

Return remaining VA hours, capRoom, and whether a new cap can be filed. Also returns the calls wallet: balance_cents is spendable after open holds, wallet_cents is that amount plus holds_cents, and holds_cents is the sum of unsettled holds. addFundsUrl is POST /api/v1/billing/add-funds and this read does not create a Stripe session. canDelegate is false when hours are unavailable, when spendable hours are not above zero, or when open caps leave no room. canDelegate false while hoursRemaining is above zero means lower maxHours to capRoom or wait. It is not a buy-hours signal. Call this before proposing spend. Does not create a task.

無需輸入參數。

delegate_task

Delegate task

Call get_balance first, then confirm with the user before sending (real hours) unless they already said to send it. Delegate a task to a real human virtual assistant when the AI cannot complete it autonomously. Use this for phone calls, owner-authorized login or captcha steps (never send passwords or OTP), physical-world actions, subjective QA, manual data entry, or anything else outside the model's reach. Returns a taskId for tracking. The job is NOT started until the customer clicks Start on Work. The receipt status is awaiting_customer_start.

輸入參數title必填dueDatemaxHoursprioritywebhookUrldescriptionsourceAgentidempotencyKey必填

list_tasks

List delegated tasks

List recently delegated tasks for this account (id, title, status, short result). awaitingCustomerConfirm true means the delivery is done and the human must confirm, cancel, or reopen. amNote is the delivery note and deliverableLinks are https links from that note. pending and in_progress omit customer-cancelled jobs. cancelled is terminal.

輸入參數status

get_task

Get delegated task

Get the current status, title, completion timestamp, and full result notes for a specific delegated task. awaitingCustomerConfirm true means ask the human, then confirm_task, cancel_task, or reopen_task. amNote is the AM or VA note. deliverableLinks lists https links. Stop when status is completed, failed, or cancelled. Customer cancel is cancelled, not pending or in_progress, and it does not send the completion webhook.

輸入參數taskId必填

confirm_task

Confirm task

Accept a delivery that is awaitingCustomerConfirm. Settles tracked hours, releases the board and ledger hold, and marks the task completed. If the human does not respond, the job confirms itself after 3 days. Ask the human first. Idempotency-Key is required. A repeat of the same key returns the same result.

輸入參數taskId必填idempotencyKey必填

cancel_task

Cancel task

Customer never mind. Releases the hold and bills only tracked time. Does not send the completion webhook. Ask the human first. Idempotency-Key is required.

輸入參數reasontaskId必填idempotencyKey必填

reopen_task

Reopen task

Send a delivery that is awaitingCustomerConfirm back to the account manager with a reason. Does not settle hours. Ask the human first. Idempotency-Key is required.

輸入參數reason必填taskId必填idempotencyKey必填

place_call

Place call

Place one human phone call. The hold is the full call: the tier minimum for the first minute, then the per-minute rate for each additional minute. Default max_minutes is 5, so a tier 1 US or Canada call holds $6.50. Raise max_minutes on that call to hold more. record_call must be false or omitted. Only US and CA are live. A question is {"id","ask","type"?}: id up to 80 characters, ask up to 1000 characters, at most 20 questions. goal is at most 4000 characters. Idempotency key is required. Poll get_call, or pass callback_url. validate_call checks the body and places no hold.

輸入參數goal必填phone必填scriptpurpose必填deadline必填languageextensionquestions必填max_minutesrecord_callscript_modetime_window另有 12 個

validate_call

Validate call

Check a phone-call body without creating a call or placing a hold. Same fields as place_call, without idempotencyKey. A ready body includes hold_cents for the full call (tier 1 default $6.50 at 5 minutes) and whether recipient_timezone was inferred. valid stays true when spendable balance is below the hold. warnings then includes insufficient_balance with needed_cents and addFundsUrl.

輸入參數goalphonescriptpurposedeadlinelanguageextensionquestionsmax_minutesrecord_callscript_modetime_window另有 11 個

get_call

Get call

Read one human phone call, including needs_info missing_fields or the final result.

輸入參數call_id必填

update_call

Update call

Fill missing_fields on a call in needs_info. Same result shapes as place_call.

輸入參數goalphonescriptcall_id必填purposedeadlinelanguageextensionquestionsmax_minutesrecord_callscript_mode另有 12 個

cancel_call

Cancel call

Cancel a call. Status stays cancel_pending until ops confirms. A confirm before any dial refunds the hold and the status becomes cancelled. If the dial already started, the error is cancel_too_late and the call bills normally. A dial after a confirmed cancel is a full refund and the VA is unpaid.

輸入參數call_id必填

get_transcript

Get transcript

Read the VA wrap-up summary for one call. This is not a recording. Once the call is wrap_up or completed, the result is that summary plus any question answers, with source wrap_up_summary and recorded false. Before a wrap-up summary exists, the result is transcript_not_ready. A call that ended without a dial (system failure or refund) is "no transcript: call not placed". A cancel after the dial started is call_cancelled. A recorded transcript may be a separate paid feature later and is not returned.

輸入參數call_id必填

版本歷史

3
  1. v0.2.1最新Oct 21, 2026
  2. v0.2.0Oct 20, 2026
  3. v0.1.3Oct 16, 2026

評分

已滿足適用檢查項的 100%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分