For AI builders · Works with Claude
Give your agent hands.
TaskQ is an MCP server where every tool is carried out by a person. Your agent plans; people do; structured evidence comes back.
Free for up to 3 people. No card.
https://taskq.isat.pt/mcp- Remote MCP server with OAuth
- Standard Webhooks to wake your runner
- People approve; the server enforces the rules
Capabilities
Tools whose executor is a human.
A capability is a step type with a contract: measure, purchase, move item. To your agent it works like any other tool. It reads the instructions, fills in the input schema and gets structured evidence back. The only difference is who runs it: a person, on their phone.
Every capability has a five-part contract
Instructions for the agent
agent_instructionsMarkdown: when to use it, how to write the step, common mistakes.
Input schema
input_schemaWhat your agent must fill in, as JSON Schema.
Evidence schema
evidence_schemaWhat comes back. Without it, the step cannot close.
Execution requirements
requirementsQualifications, resources and the kind of location.
Rules the server enforces
rulesPer-request limit, approval threshold, budget and risk.
Rules live on the server; guidance lives in text. Your agent can propose anything. It cannot talk its way past a spending limit, because TaskQ enforces it.
key: purchase
version: 1
name:
en: Purchase
pt-PT: Compra
agent_instructions: |
Use when the task is missing material. Always give an estimated price
and an alternative in case the item is out of stock.
input_schema:
item: string
quantity: number
suggested_store: string
estimated_price: { amount: number, currency: string }
evidence_schema:
- kind: document
description: invoice issued to the workspace tax ID
requirements:
qualifications: []
rules:
max_per_request: { amount: 50, currency: EUR }
approval_above: { amount: 50, currency: EUR }
budget: task
default_gadget: purchase-receipt
risk: medium10 capabilities ready on day one
Capabilities are configurable and versioned, like skills, and none of them is hard-coded. Your agent can propose a new capability or a new version; each one goes through an approval request.
label_locationStick a printed label with a readable code (like A3) on a location and photograph it.
photographPhotograph a location, object or state, as a reference or for your agent to read.
inventory_locationList what is inside a location, with quantities and a photo, optionally emptying it into a staging area.
move_itemMove items from one location to another and photograph them in their new place.
measureMeasure a dimension or quantity with a tool and report the value in a given unit.
purchaseGet missing material from a shop and bring back an invoice issued to the workspace tax ID. TaskQ records it; it never moves money.
transport_resourceTake a tool, vehicle or material to another site or address and record where it is.
operate_toolUse a tool or machine (laser cutter, 3D printer, drill) for a defined operation, following safety notes.
verify_resultCheck the result against explicit criteria and photograph the final state.
sync_with_orchestratorA short on-site meeting between operators and the orchestrator, with a written summary.
MCP server
One remote MCP server. 16 tools. People on the other end.
Add TaskQ to claude.ai or Claude Code as a custom connector. Your agent reads the workspace, proposes phases and reads the evidence people send back.
Remote, over Streamable HTTP
Nothing to install or host. Point your client at the endpoint.
OAuth sign-in
You sign in with your TaskQ account and choose the workspace. No API keys to paste or leak.
One orchestrator, one workspace
Each token is bound to one member with the orchestrator role and only sees that member’s workspace. Every tool call checks the role again.
English for machines
Tool names, descriptions, parameters and errors are in English, whatever language your people work in.
Connect your client
https://taskq.isat.pt/mcpclaude.ai and the Claude apps: Settings → Connectors → Add custom connector. Paste the endpoint, sign in to TaskQ and choose the workspace.
Claude Code: add the server, then run /mcp to sign in.
Only orchestrators can connect. If your Claude organisation hides the option, ask its admin to allow custom connectors.
claude mcp add --transport http taskq https://taskq.isat.pt/mcpAll 16 tools
- Read
- Reads current state, nothing else.
- Proposal
- Opens an approval request. Nothing happens until a person approves.
- Direct write
- Writes directly, inside the token’s workspace.
| Tool | What it does | Effect |
|---|---|---|
get_workspace | Sites, location map, resources and their state, members with qualifications and aggregated availability | Read |
list_capabilities | Catalogue with contracts and default gadgets | Read |
list_gadgets | Library of approved gadgets, with data schemas | Read |
create_task | Title, goal, site, budget and who decides at decision points | Direct write |
propose_phase | Batch of steps with inputs, locations, resources, dependencies, blocks, gadgets and attachments | Proposal |
propose_capability | New capability or new version of an existing one | Proposal |
propose_gadget | Code, schema and sample data for preview | Proposal |
propose_map_change | New locations, labels or layout | Proposal |
get_task | State, phases, steps and exceptions | Read |
get_evidence | Photos (as images), measurements, documents and annotations for a step or a phase | Read |
attach_file | Uploads an agent file to attach to a proposed step (e.g. a drawing or a materials list) | Direct write |
list_unarchived_files | Files submitted by operators and not yet archived, per task or across the workspace | Read |
get_file | File content in the response, plus a signed link valid for a few minutes | Read |
mark_file_archived | Marks a file as archived with the destination reference and starts the retention period | Direct write |
list_pending_decision_points | What is waiting for a decision, per task | Read |
close_task | Closes the task with a summary | Direct write |
Errors your agent can act on
propose_phase checks everything before it opens the approval request: the capabilities exist, inputs match their schemas, budget rules hold, resources and locations are known and dependencies are acyclic. It returns every error at once, so your agent fixes them in one pass.
Proposals by default
Everything your agent writes is a proposal, except what the workspace marks for auto-approval by risk level (Premium, off by default).
Parallel work · Many hands, no collisions
Parallel by declaration.
Your agent declares each step’s dependencies, exclusive resources and location. The dispatcher works out what can run at the same time, like threads with locks. If you have written multithreaded code, you already know the model. Your agent never has to schedule anyone.
- Operator 1 runs a block: Empty A3, Measure A3, Measure A4. The block holds the caliper from start to finish.
- At the same time, Operator 2 empties and photographs B1.
- Measure B2 also needs the caliper, so it waits until the block releases it. The two measuring steps never overlap.
- Carry cabinet needs two people: the dispatcher reserves both operators together.
Exclusive tools and places are locks
A caliper, a car, a drawer: one person at a time. Reservations are Postgres
tstzrangevalues under anEXCLUDE USING gistconstraint, so two reservations of the same resource can never overlap.Blocks reserve all-or-nothing
A block keeps a sequence of steps with one person and reserves all its resources at the start, or none of them. No deadlocks between two people waiting on each other.
Steps for several people
Carry a cabinet, sync with the orchestrator: a step can require several people, and the dispatcher reserves them together.
Deterministic, and it says why
No AI model in the dispatcher. It filters by qualifications, site access, availability and free resources and locations, balances workload, and stores a readable reason with each assignment.
{
"ref": "measure-A3",
"capability_key": "measure",
"title": "Measure drawer A3",
"instruction": "Measure the inside width of drawer A3, wall to wall.",
"source_locale": "en",
"input": { "target": "drawer A3", "dimension": "inside width", "unit": "mm" },
"location_id": "<drawer A3>",
"resources": [{ "resource_id": "<caliper>" }],
"depends_on": ["empty-A3"],
"block_ref": "measuring-round",
"people_required": 1
}“Has access to Workshop, caliper free, free until 18:00”
Standard Webhooks
Signed events, the standard way.
TaskQ sends events by webhook, so your runner, an automation or another tool can react without anyone opening Claude. Webhooks are outgoing only.
13 events
| Event | Fires when |
|---|---|
task.created | A task is created |
phase.proposed | The agent proposes a phase and the approval request opens |
phase.approvedphase.rejected | The orchestrator decides on the phase |
step.assigned | The dispatcher assigns a step |
step.done | The evidence is submitted and validated |
step.blocked | An operator taps Can’t do it or Stop for safety |
decision_point.opened | The phase closed, or an exception blocked the rest of it |
file.uploaded | An operator submits a file |
file.archive_overdue | The archive period passes without the file being marked |
approval.requestedapproval.decided | Purchase, schedule, gadget, capability or personal resource |
task.closed | The task is closed |
Signature
- Headers
webhook-id,webhook-timestamp,webhook-signature, as in the Standard Webhooks specification. - HMAC-SHA256 over the id, timestamp and body, with a
whsec_secret. - Rotate secrets without downtime: during rotation each request carries two signatures.
- Reject anything older than 300 seconds. The standard libraries do it for you.
Delivery
- At-least-once, with retries at increasing intervals. The
webhook-idstays the same across retries, so deduplicate on it. - Order is not guaranteed. Each event carries a per-task sequence number,
task_sequence, so you can reorder. - After repeated failures the subscription is suspended and admins are notified. The console shows the delivery log, with manual redelivery and a test event.
Only admins create webhooks, in the console
The MCP server cannot create or change webhooks. An instruction hidden in a file or a photo cannot redirect your events to someone else’s URL. URLs must be HTTPS, private and loopback addresses are refused, and redirects are not followed.
Webhook endpoints: 1 on Free, 25 on Premium.
Minimal bodies
Ids and a console link, nothing more. Fetch the details through MCP with your own credentials, so you always read current data. Events never carry time records, detail preferences, full names or file contents.
{
"id": "0b6f3c1e-5d2a-4f7e-9a51-2c8d4e6f7a90",
"type": "decision_point.opened",
"timestamp": "2026-11-09T15:42:07.000Z",
"workspace_id": "5a1e9d3b-7c40-4b8e-a2f1-93d6c0e4b215",
"task_sequence": 7,
"data": {
"task_id": "c3d9a7f2-1b6e-4e0a-8f53-6a2b9d1c4e78",
"phase_id": "e81f4b26-9c3a-4d57-b0e2-7f5a1c8d3b49",
"decision_point_id": "4f2a8c61-3e9b-4d0f-a7c5-1b6e2d9f8a30",
"reason": "phase_closed"
},
"links": { "console": "https://taskq.isat.pt/console/tasks/c3d9a7f2-1b6e-4e0a-8f53-6a2b9d1c4e78" }
}npm install standardwebhooksimport { Webhook } from "standardwebhooks";
const wh = new Webhook(process.env.TASKQ_WEBHOOK_SECRET!); // "whsec_..."
export async function handle(req: Request): Promise<Response> {
const body = await req.text(); // the raw body, before JSON.parse
try {
// HMAC-SHA256 check; rejects timestamps more than 5 minutes off
const event = wh.verify(body, Object.fromEntries(req.headers)) as { id: string; type: string };
if (event.type === "decision_point.opened") await wakeRunner(event); // dedupe on event.id
return new Response(null, { status: 204 });
} catch {
return new Response("Invalid signature", { status: 400 });
}
}Runner mode
Nobody has to paste a prompt.
By default, the orchestrator gets a ready-to-send prompt for Claude at each decision point. Connect a runner of your own and the loop moves on by itself, up to the one step that stays human: approval.
decision_point.openedA phase closes, or an exception blocks the rest of it. TaskQ signs the event and sends it.
Your runner wakes up
It verifies the signature and calls the TaskQ MCP server.
It reads, then proposes
get_taskandget_evidencefor what happened;propose_phasefor what comes next, orclose_task.A person approves
The proposal waits in the approvals inbox. Automation speeds up the loop; the orchestrator keeps the decision.
The dispatcher assigns
Steps go to whoever is free, has access and has the tool, with the reason stored.
Same pattern for file.uploaded: archive an invoice in your own system the moment it is submitted, then call mark_file_archived.
Custom step screens
A screen made for the job. Sandboxed.
Your agent can draw the step: the cabinet with the active drawer lit, a grid to tick off what came out of a drawer. Gadgets run inside a fixed frame that belongs to the app.
The fixed frame (the app)
- Context at the top, such as “Step 2 of 5 · Tidy cabinet A”
- Instruction, location and required evidence
- Done, Can’t do it, More detail and Stop for safety, always outside the gadget
- The camera and file uploads, which never belong to the gadget
The gadget (sandboxed iframe)
sandbox="allow-scripts", neverallow-same-originThe gadget runs with an opaque origin: no access to the app, its session or its storage.
A CSP that blocks all network access
default-src 'none': no fetch, no beacons, no external images or fonts.Approved with its phase
New gadgets are approved together with their phase, with a preview using real data in the console. Approved gadgets join the library.
A four-method postMessage API
| Method | What it does |
|---|---|
getStepData() | Step, gadget data, the operator’s locale, the location branch and the evidence requirements. |
requestPhoto({ prompt }) | Asks the app to open its camera flow and resolves with the evidence id. |
submitEvidence({ kind, value }) | Hands evidence to the app, which validates and stores it. |
markReady() | Tells the app the operator can now tap Done. |
Built in on every plan: cabinet-diagram, item-checklist, purchase-receipt. Step screens made by your agent are part of Premium.
{ taskq: 1, id, type: "request", method, params }
{ taskq: 1, id, type: "response", result | error }Fair to people
What the API never returns.
Your agent plans the work. It never gets a view into the people doing it.
Time records
Clock-ins, breaks and attendance are never exposed to your agent.
Detail preferences
How much detail each person prefers is theirs alone. It never affects who gets what.
Individual durations
Duration estimates are corrected per capability, never per person.
Webhook events carry ids, never names. The dispatcher never scores people or ranks them on performance; it balances workload instead.
Build on Free. Scale on Premium.
The MCP server and all 16 tools are on every plan, Free included. Planning runs on your own Claude.
| Feature | Free | Premium |
|---|---|---|
| MCP server, all 16 tools | ||
| Webhooks (Standard Webhooks) | 1 endpoint | 25 endpoints |
| Wake your own agent on decision points | uses the webhook | |
| Auto-approval by risk level | off by default | |
| Built-in step screens (cabinet diagram, item checklist, purchase receipt) | ||
| Custom step screens made by the agent | Unlimited |
Your Claude plan is separate and billed by Anthropic. TaskQ's price covers AI Assist.
Your agent plans. Your people do. You approve.
Create a free workspace, open the Connect Claude page in the console and add TaskQ to claude.ai or Claude Code as a custom connector.
Free for up to 3 people. No card.
Public API reference Coming soon
Until it ships, the MCP tool descriptions and the in-app Connect Claude page cover what your agent needs.
Claude is a trademark of Anthropic.