cyberdyne-mcp 0.6.2 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.js CHANGED
@@ -13,13 +13,13 @@
13
13
  * get_deposit_address — GET /api/treasury/deposit → where to send real USDC (live)
14
14
  * deposit — POST /api/treasury/deposit → credit treasury from a real USDC tx
15
15
  * withdraw_treasury — POST /api/treasury/withdraw → pull unspent treasury back to your wallet (live)
16
- * post_task — POST /api/tasks → open a task
17
- * assign_task — POST /api/tasks/[id]/assign pick a human (→ authIntent)
18
- * authorize_task — POST /api/tasks/[id]/authorize → open the escrow hold
16
+ * post_task — POST /api/tasks → open an FCFS pool bounty
17
+ * authorize_task — POST /api/tasks/[id]/authorize sign budget + pay fee + freeze
19
18
  * get_task — GET /api/tasks/[id] → status + submissions/claims
20
- * release_payment — POST /api/tasks/[id]/release direct-hire: capture (pay) or reject
21
- * review_submission — POST /api/submissions/[id]/review pool/FCFS: approve/reject one submission
22
- * close_task — POST /api/tasks/[id]/close close a (multi-unit) bounty
19
+ * review_submission — POST /api/submissions/[id]/review approve (pay one unit) / reject (reopen)
20
+ * close_task — POST /api/tasks/[id]/close refund the unfilled budget
21
+ * assign_task — POST /api/tasks/[id]/assign DEPRECATED (testnet-only; no direct hire)
22
+ * release_payment — POST /api/tasks/[id]/release → DEPRECATED (testnet-only; use review_submission)
23
23
  *
24
24
  * Auth: every networked tool sends the agent's `cyb_…` key. The REST routes take
25
25
  * it as `Authorization: Bearer …`; search_humans goes through the a2a JSON-RPC
@@ -27,26 +27,24 @@
27
27
  * `identity_token`.
28
28
  *
29
29
  * The HUMAN submit-proof step happens in the app/UI (human-only — agents cannot
30
- * submit on a human's behalf). There are TWO settlement flows:
30
+ * submit on a human's behalf). There is ONE settlement model for real tokens:
31
31
  *
32
- * FLOW A DIRECT HIRE (the path that works TODAY on the live custodial USDC
33
- * rail: real deposit escrow withdraw on Base mainnet). You pick one human:
34
- * get_deposit_address send USDC deposit (fund the treasury)
35
- * post_task search_humans assign_task (→ authIntent)
36
- * authorize_task (open the escrow hold)
37
- * poll get_task until a submission is pending
38
- * → release_payment (approvecapture/pay; else reject refund)
32
+ * FCFS POOL BOUNTY (non-custodial pool escrow). There is NO direct hire and NO
33
+ * agent-picks-human. EVERY task is an open bounty: the agent freezes a budget once,
34
+ * ANY eligible human submits first-come-first-served, and the agent approves/rejects
35
+ * each submission approved pays one unit in-token, rejected reopens the slot, and
36
+ * any unfilled budget is refunded on close.
37
+ * get_deposit_address send USDC deposit (optional, fund treasury)
38
+ * → post_task({ ..., quantity }) returns { task, authIntent, deployFee }
39
+ * → authorize_task({ task_id, auth_intent, deploy_fee }) (sign budget + pay fee + freeze)
40
+ * → humans submit FCFS → poll get_task
41
+ * → review_submission per pending submission (approve → pay one unit;
42
+ * reject → the slot reopens)
43
+ * → close_task to refund the unfilled budget.
39
44
  *
40
- * FLOW B POOL / FCFS BOUNTY (non-custodial pool escrow). Post a multi-unit
41
- * bounty, freeze the whole budget once, and let any eligible human claim+submit
42
- * first-come-first-served; you approve each unit. This rail is BUILT but GATED
43
- * OFF today (server env ESCROW_POOL is not enabled), pending certification — so
44
- * real-money non-custodial pool payouts are NOT live yet. When the server
45
- * enables it, post_task returns an `authIntent` + a separate `deployFee`:
46
- * post_task (quantity>1) → authorize_task (sign the budget + pay the deploy fee)
47
- * → humans claim+submit FCFS → poll get_task
48
- * → review_submission per pending submission (approve → capture one unit;
49
- * reject → the slot reopens) → close_task to refund unfilled units.
45
+ * DEPRECATED (testnet-only): assign_task + release_payment were the old direct-hire
46
+ * path. There is no direct hire for real tokens a real-token assign/release returns
47
+ * 409 direct_hire_retired. The tools remain only for the testnet/non-real demo rail.
50
48
  *
51
49
  * Config comes from the environment (see src/client.ts):
52
50
  * CYBERDYNE_API_URL default "https://app.cyberdyne-os.xyz"
@@ -154,7 +152,7 @@ async function guard(fn) {
154
152
  }
155
153
  }
156
154
  // ---- Server ---------------------------------------------------------------
157
- const server = new McpServer({ name: "cyberdyne", version: "0.6.2" });
155
+ const server = new McpServer({ name: "cyberdyne", version: "0.6.3" });
158
156
  server.tool("list_categories", "List the kinds of real-world work CYBERDYNE humans can do. Static (no network). Use this to learn the valid `category` values before posting a task.", {}, async () => json(Object.entries(CATEGORIES).map(([id, blurb]) => ({ id, blurb }))));
159
157
  server.tool("onboard", "BOOTSTRAP (works WITHOUT an existing key — the one tool that self-onboards). Zero-browser: generates a fresh wallet if you don't have one, signs in to CYBERDYNE with it (SIWE), mints your `cyb_` agent API key, and saves both to ~/.cyberdyne/config.json (0600) so every other tool here authenticates automatically. No web dashboard, no env vars. Returns your wallet address, the cyb_ key (shown once), and the next steps (fund via get_deposit_address+deposit → post_task → assign → authorize → release). The same generated wallet auto-signs pool budgets. Idempotent-ish: re-running with a saved wallet reuses it and mints a fresh key.", {}, async () => guard(async () => {
160
158
  const r = await onboard();
@@ -189,7 +187,7 @@ server.tool("deposit", "Credit your treasury from a REAL on-chain USDC deposit (
189
187
  .describe("The Base tx hash of your USDC transfer to the deposit address."),
190
188
  }, async ({ tx_hash }) => guard(() => client.rest("POST", "/api/treasury/deposit", { body: { tx_hash } })));
191
189
  server.tool("withdraw_treasury", "Recover UNSPENT treasury to your wallet (live rail): pull USDC out of your treasury back to your own VERIFIED deposit wallet on Base — no browser. Available balance is your treasury balance net of any open escrow holds. Funds can ONLY go to your verified wallet (no destination param), so a leaked key can't redirect them. Returns { ok, tx_hash, amount_usd, to }. 400 insufficient_treasury if the balance can't cover it; 403 withdraws_disabled on the demo rail.", { amount_usd: z.number().positive().describe("USD to withdraw from your treasury to your verified wallet.") }, async ({ amount_usd }) => guard(() => client.rest("POST", "/api/treasury/withdraw", { body: { amount_usd } })));
192
- server.tool("post_task", "Open a task on the marketplace. Funds are NOT charged at post — the escrow hold opens later at authorize_task. `reward_usd` is the total budget; with quantity>1 each unit holds reward_usd/quantity (each unit must be >= $0.01). Returns the created task (with its id). DIRECT-HIRE / custodial rail (the path live today): the platform checks the prefunded treasury can cover the budget (402 insufficient_treasury otherwise); response is { task }. POOL/FCFS rail (only when the server enables it): response also includes `authIntent` (the budget authorization to sign) and `deployFee` { usd, bps, recipient, token } (a SEPARATE non-refundable fee tx) — pass both to authorize_task.", {
190
+ server.tool("post_task", "Open an FCFS pool bounty on the marketplace. There is NO direct hire and NO agent-picks-human — every task is an open bounty: you freeze a budget, ANY eligible human submits first-come-first-served, and you approve/reject each submission. Funds are NOT charged at post — the budget is frozen later at authorize_task. `reward_usd` is the total budget; `quantity` is how many identical units (humans) it pays — each unit holds reward_usd/quantity (each unit must be >= $0.01). Returns the created task (with its id). REAL-TOKEN POOL rail (USDC/BNKR on Base): the response also includes `authIntent` (the budget authorization to sign) and `deployFee` { usd, bps, recipient, token } (a SEPARATE non-refundable fee tx) — pass BOTH to authorize_task. TESTNET/non-real token (CYOS): no on-chain freeze; response is just { task } (treasury-checked, 402 insufficient_treasury if low).", {
193
191
  title: z.string().min(2).max(160).describe("Short task title."),
194
192
  category: z.enum(TASK_CATEGORIES),
195
193
  description: z.string().max(4000).optional().describe("What you need the human to do."),
@@ -201,11 +199,11 @@ server.tool("post_task", "Open a task on the marketplace. Funds are NOT charged
201
199
  pay_token: z.enum(["USDC", "BNKR", "CYOS"]).optional().describe("Settlement token (default USDC)."),
202
200
  deadline_hours: z.number().int().positive().optional(),
203
201
  }, async (args) => guard(() => client.rest("POST", "/api/tasks", { body: args })));
204
- server.tool("assign_task", "Assign an open task to a chosen human (poster-only) and open the escrow intent. Returns `{ task, authIntent }`: on an on-chain rail `authIntent` is the auth-capture requirements the agent must sign; on the manual rail it is null. Next call authorize_task to actually open the hold.", {
202
+ server.tool("assign_task", "DEPRECATED — TESTNET/DEMO ONLY. There is NO direct hire: every real-token task is an open FCFS pool bounty, so a real-token assign returns 409 direct_hire_retired ('post with a budget; humans submit FCFS; review each submission'). Do NOT use this to hire post_task + authorize_task + review_submission is the flow. This tool remains only for the testnet/non-real (CYOS) demo rail, where it assigns an open task to a chosen human and returns `{ task, authIntent: null }`.", {
205
203
  task_id: z.string().uuid(),
206
204
  human_id: z.string().uuid().describe("The human profile id (from search_humans / get_task claims)."),
207
205
  }, async ({ task_id, human_id }) => guard(() => client.rest("POST", `/api/tasks/${task_id}/assign`, { body: { human_id } })));
208
- server.tool("authorize_task", "Open the escrow hold for a task. CUSTODIAL/MANUAL rail (the path live today): call with just { task_id } — the prefunded treasury is debited into a logical escrow hold, no signature needed. TRUSTLESS on-chain DIRECT-HIRE rail: the agent signs an auth-capture authorization — if CYBERDYNE_EVM_PRIVATE_KEY is set pass `auth_intent` (the authIntent from assign_task) and the MCP signs automatically, else pass a pre-signed `signed_payment`. POOL/FCFS rail (only when the server enables it): pass BOTH `auth_intent` (from post_task) AND `deploy_fee` (the deployFee object from post_task) — the MCP signs the budget and pays the separate 2.5% USDC / 5% other-token fee tx from its wallet, then submits both; or pass a pre-signed `signed_payment` and a pre-paid `fee_tx_hash`. Idempotent once held.", {
206
+ server.tool("authorize_task", "Freeze the bounty budget on-chain (the second step of the FCFS flow). REAL-TOKEN POOL rail: pass BOTH `auth_intent` (the authIntent from post_task) AND `deploy_fee` (the deployFee object from post_task) — with CYBERDYNE_EVM_PRIVATE_KEY set, the MCP signs the whole-budget authorization AND pays the separate 2.5% USDC / 5% other-token deploy fee tx from its wallet, then freezes the budget on the audited escrow; or pass a pre-signed `signed_payment` and a pre-paid `fee_tx_hash`. After this, any eligible human submits FCFS and you review_submission each. TESTNET/non-real (CYOS) rail: call with just { task_id } — the prefunded treasury opens a logical hold, no signature. Idempotent once frozen.", {
209
207
  task_id: z.string().uuid(),
210
208
  signed_payment: z.string().optional().describe("Pre-signed base64 auth-capture payload (external/Bankr signer)."),
211
209
  auth_intent: z.unknown().optional().describe("The authIntent from assign_task/post — required for MCP wallet auto-signing."),
@@ -237,8 +235,8 @@ server.tool("authorize_task", "Open the escrow hold for a task. CUSTODIAL/MANUAL
237
235
  },
238
236
  });
239
237
  }));
240
- server.tool("get_task", "Get the live state of a task: the task row plus the submissions and per-unit claims the agent (as poster) may see. Poll this after authorize_task until a submission with status 'pending' appears — that is the human's proof, ready for release_payment.", { task_id: z.string().uuid() }, async ({ task_id }) => guard(() => client.rest("GET", `/api/tasks/${task_id}`)));
241
- server.tool("release_payment", "DIRECT-HIRE settle (poster-only): settle a submitted proof for a single-human task (the custodial-rail path live today). approve:true CAPTURE: pay the human net of the platform fee. approve:false REJECT/REFUND the held escrow. Requires the `submission_id` to act on; if omitted, the gateway fetches the task and uses the latest pending submission (and errors if none is pending yet poll get_task first). For POOL/FCFS bounties use review_submission instead (this path captures the whole task hold, not one unit).", {
238
+ server.tool("get_task", "Get the live state of a task: the task row plus the submissions and per-unit claims the agent (as poster) may see. Poll this after authorize_task until a submission with status 'pending' appears — that is the human's proof, ready for review_submission (approve pays one unit; reject reopens the slot).", { task_id: z.string().uuid() }, async ({ task_id }) => guard(() => client.rest("GET", `/api/tasks/${task_id}`)));
239
+ server.tool("release_payment", "DEPRECATED TESTNET/DEMO ONLY. There is NO direct hire: a real-token task is an FCFS pool bounty whose units settle ONE per approved submission, so a real-token release returns 409 direct_hire_retired use review_submission instead (approve pays one unit, reject reopens the slot). This tool remains only for the testnet/non-real (CYOS) demo rail, where it settles a submitted proof for a single-human task: approve:true pay net of fee, approve:false reject/refund. `submission_id` auto-resolves to the latest pending one if omitted.", {
242
240
  task_id: z.string().uuid(),
243
241
  approve: z.boolean().describe("true = proof meets criteria → pay; false = reject/refund."),
244
242
  submission_id: z
@@ -269,7 +267,7 @@ server.tool("release_payment", "DIRECT-HIRE settle (poster-only): settle a submi
269
267
  },
270
268
  });
271
269
  }));
272
- server.tool("review_submission", "POOL / FCFS settle (poster-only): approve or reject ONE submission on a pool bounty. approve:true → CAPTURE one unit from the frozen pool budget to the human and consume a slot; approve:false → reject (the slot reopens for the next submitter — no spot-blocking). For single-human direct-hire tasks use release_payment instead. Poll get_task for pending submissions. NOTE: the pool/FCFS rail is gated off on the server until certification this tool acts on pool tasks once the operator enables that rail.", {
270
+ server.tool("review_submission", "THE settle tool (poster-only): approve or reject ONE submission on your FCFS pool bounty — this is how you pay humans (there is no direct hire). approve:true → CAPTURE one unit from the frozen budget to the human (full reward, in-token) and consume a slot; approve:false → reject (the slot reopens for the next submitter — no spot-blocking). Poll get_task for pending submissions and review each one. When the budget is consumed (or you're done) call close_task to refund the unfilled remainder.", {
273
271
  submission_id: z.string().uuid().describe("The pending submission to review (from get_task)."),
274
272
  approve: z.boolean().describe("true = proof meets criteria → capture one unit; false = reject (slot reopens)."),
275
273
  score: z.number().int().min(1).max(5).optional().describe("Rating of the human's work (1–5)."),
@@ -283,14 +281,14 @@ server.tool("review_submission", "POOL / FCFS settle (poster-only): approve or r
283
281
  ...(reject_reason ? { reject_reason } : {}),
284
282
  },
285
283
  })));
286
- server.tool("close_task", "Close a (multi-unit) bounty (poster-only): refund every still-held unit to the agent, mark unclaimed units done, and stop further claims. Idempotent on an already-closed task.", { task_id: z.string().uuid() }, async ({ task_id }) => guard(() => client.rest("POST", `/api/tasks/${task_id}/close`)));
284
+ server.tool("close_task", "Close your FCFS pool bounty (poster-only): refund the unfilled budget back to your wallet on-chain (the uncaptured remainder = unfilled units × per-unit reward) and stop further submissions. The deploy fee is non-refundable. Idempotent on an already-closed task.", { task_id: z.string().uuid() }, async ({ task_id }) => guard(() => client.rest("POST", `/api/tasks/${task_id}/close`)));
287
285
  // ---- Self-onboarding prompt -----------------------------------------------
288
286
  // Surfaces as /mcp__cyberdyne__quickstart — the agent (or user) runs it once to
289
287
  // learn the end-to-end campaign flow without reading docs. This is the "skill"
290
288
  // shipped inside the MCP: guidance travels with the tools.
291
289
  server.registerPrompt("quickstart", {
292
290
  title: "CYBERDYNE quickstart",
293
- description: "How to fund, post a task, and pay humans end-to-end — both the direct-hire and pool/FCFS flows.",
291
+ description: "How to fund, post an FCFS pool bounty, and pay verified humans end-to-end.",
294
292
  }, () => ({
295
293
  messages: [
296
294
  {
@@ -298,26 +296,20 @@ server.registerPrompt("quickstart", {
298
296
  content: {
299
297
  type: "text",
300
298
  text: [
301
- "You are connected to CYBERDYNE — hire and pay verified humans for tasks AI can't do alone. The live settlement rail is REAL USDC on Base (custodial: deposit -> escrow -> withdraw). The human submit-proof step is human-only, in the app; you drive everything else.",
299
+ "You are connected to CYBERDYNE — pay verified humans for tasks AI can't do alone. There is ONE model: every task is an open FCFS pool bounty. There is NO direct hire and NO picking a human — you freeze a budget, ANY eligible human submits first-come-first-served, and you approve/reject each submission (approved = paid one unit in-token, rejected = the slot reopens). The live settlement rail is REAL tokens on Base (non-custodial freeze-at-deploy). The human submit-proof step is human-only, in the app; you drive everything else.",
302
300
  "",
303
- "FUND (real money, custodial rail):",
301
+ "FUND (optional — the pool freezes from your wallet at deploy, but a treasury can cover fees):",
304
302
  "1. get_deposit_address -> the platform deposit address on Base.",
305
- "2. Send USDC to it FROM your own verified wallet (the one you signed in with).",
306
- "3. deposit({ tx_hash }) -> credits your treasury by the verified amount (idempotent).",
307
- " (fund_treasury is demo/testnet only and is disabled on the live rail.)",
308
- "Check get_treasury anytime for your balance.",
303
+ "2. Send USDC to it FROM your own verified wallet, then deposit({ tx_hash }) -> credits your treasury (idempotent).",
304
+ " (fund_treasury is demo/testnet only and is disabled on the live rail.) Check get_treasury anytime.",
309
305
  "",
310
- "FLOW A - DIRECT HIRE (works today): pick one human, hold, then pay.",
311
- "4. post_task({ title, category, reward_usd, duration_min, difficulty }). Returns { task }. Use reward_usd >= 0.50 so the 2.5% fee is visible; each unit must be >= $0.01.",
312
- "5. search_humans({ skills, min_reputation }) -> assign_task({ task_id, human_id }) -> authorize_task({ task_id }) to open the escrow hold (custodial rail = no signature; just task_id).",
313
- "6. Poll get_task until a submission is pending (the human's proof).",
314
- "7. release_payment({ task_id, approve: true, score }) -> CAPTURE: net USDC to the human, the 2.5% fee to the protocol wallet. approve:false rejects and refunds the hold.",
306
+ "POST + PAY (the single FCFS flow):",
307
+ "3. post_task({ title, category, reward_usd, quantity, duration_min, difficulty }) -> returns { task, authIntent, deployFee }. reward_usd is the TOTAL budget; quantity is how many humans it pays (each unit must be >= $0.01). authIntent is the whole-budget authorization; deployFee is a SEPARATE non-refundable fee tx (2.5% USDC / 5% other token).",
308
+ "4. authorize_task({ task_id, auth_intent, deploy_fee }) -> with CYBERDYNE_EVM_PRIVATE_KEY set, the MCP signs the budget AND pays the deploy fee, then FREEZES the whole budget on the audited escrow (or pass pre-made signed_payment + fee_tx_hash).",
309
+ "5. Any eligible human submits FCFS. Poll get_task; for EACH pending submission call review_submission({ submission_id, approve, score }) -> approve captures one unit (full reward to the human, in-token); reject reopens the slot for the next submitter.",
310
+ "6. close_task({ task_id }) -> refunds the unfilled budget back to your wallet (the deploy fee is non-refundable).",
315
311
  "",
316
- "FLOW B - POOL / FCFS BOUNTY: one frozen budget, many humans claim+submit first-come-first-served. NOTE: this non-custodial pool rail is BUILT but GATED OFF on the server today (pending certification) - real-money pool payouts are not live yet. When the operator enables it:",
317
- "8. post_task({ ..., quantity: N }) -> returns { task, authIntent, deployFee }. authIntent is the budget authorization; deployFee is a SEPARATE non-refundable fee tx (2.5% USDC / 5% other token).",
318
- "9. authorize_task({ task_id, auth_intent, deploy_fee }) -> with CYBERDYNE_EVM_PRIVATE_KEY set, the MCP signs the budget AND pays the deploy fee, then freezes the whole budget (or pass pre-made signed_payment + fee_tx_hash).",
319
- "10. Humans claim+submit FCFS. Poll get_task; for each pending submission call review_submission({ submission_id, approve, score }) -> approve captures one unit; reject reopens the slot.",
320
- "11. close_task({ task_id }) -> refund any still-unfilled units (the deploy fee is non-refundable).",
312
+ "DEPRECATED: assign_task + release_payment were the old direct-hire path and now return 409 direct_hire_retired for real tokens use post_task + authorize_task + review_submission instead. They remain only for the testnet/non-real (CYOS) demo rail.",
321
313
  "",
322
314
  "Every payout and fee on the live rail is a real on-chain transaction.",
323
315
  ].join("\n"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyberdyne-mcp",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/server.ts CHANGED
@@ -13,13 +13,13 @@
13
13
  * get_deposit_address — GET /api/treasury/deposit → where to send real USDC (live)
14
14
  * deposit — POST /api/treasury/deposit → credit treasury from a real USDC tx
15
15
  * withdraw_treasury — POST /api/treasury/withdraw → pull unspent treasury back to your wallet (live)
16
- * post_task — POST /api/tasks → open a task
17
- * assign_task — POST /api/tasks/[id]/assign pick a human (→ authIntent)
18
- * authorize_task — POST /api/tasks/[id]/authorize → open the escrow hold
16
+ * post_task — POST /api/tasks → open an FCFS pool bounty
17
+ * authorize_task — POST /api/tasks/[id]/authorize sign budget + pay fee + freeze
19
18
  * get_task — GET /api/tasks/[id] → status + submissions/claims
20
- * release_payment — POST /api/tasks/[id]/release direct-hire: capture (pay) or reject
21
- * review_submission — POST /api/submissions/[id]/review pool/FCFS: approve/reject one submission
22
- * close_task — POST /api/tasks/[id]/close close a (multi-unit) bounty
19
+ * review_submission — POST /api/submissions/[id]/review approve (pay one unit) / reject (reopen)
20
+ * close_task — POST /api/tasks/[id]/close refund the unfilled budget
21
+ * assign_task — POST /api/tasks/[id]/assign DEPRECATED (testnet-only; no direct hire)
22
+ * release_payment — POST /api/tasks/[id]/release → DEPRECATED (testnet-only; use review_submission)
23
23
  *
24
24
  * Auth: every networked tool sends the agent's `cyb_…` key. The REST routes take
25
25
  * it as `Authorization: Bearer …`; search_humans goes through the a2a JSON-RPC
@@ -27,26 +27,24 @@
27
27
  * `identity_token`.
28
28
  *
29
29
  * The HUMAN submit-proof step happens in the app/UI (human-only — agents cannot
30
- * submit on a human's behalf). There are TWO settlement flows:
30
+ * submit on a human's behalf). There is ONE settlement model for real tokens:
31
31
  *
32
- * FLOW A DIRECT HIRE (the path that works TODAY on the live custodial USDC
33
- * rail: real deposit escrow withdraw on Base mainnet). You pick one human:
34
- * get_deposit_address send USDC deposit (fund the treasury)
35
- * post_task search_humans assign_task (→ authIntent)
36
- * authorize_task (open the escrow hold)
37
- * poll get_task until a submission is pending
38
- * → release_payment (approvecapture/pay; else reject refund)
32
+ * FCFS POOL BOUNTY (non-custodial pool escrow). There is NO direct hire and NO
33
+ * agent-picks-human. EVERY task is an open bounty: the agent freezes a budget once,
34
+ * ANY eligible human submits first-come-first-served, and the agent approves/rejects
35
+ * each submission approved pays one unit in-token, rejected reopens the slot, and
36
+ * any unfilled budget is refunded on close.
37
+ * get_deposit_address send USDC deposit (optional, fund treasury)
38
+ * → post_task({ ..., quantity }) returns { task, authIntent, deployFee }
39
+ * → authorize_task({ task_id, auth_intent, deploy_fee }) (sign budget + pay fee + freeze)
40
+ * → humans submit FCFS → poll get_task
41
+ * → review_submission per pending submission (approve → pay one unit;
42
+ * reject → the slot reopens)
43
+ * → close_task to refund the unfilled budget.
39
44
  *
40
- * FLOW B POOL / FCFS BOUNTY (non-custodial pool escrow). Post a multi-unit
41
- * bounty, freeze the whole budget once, and let any eligible human claim+submit
42
- * first-come-first-served; you approve each unit. This rail is BUILT but GATED
43
- * OFF today (server env ESCROW_POOL is not enabled), pending certification — so
44
- * real-money non-custodial pool payouts are NOT live yet. When the server
45
- * enables it, post_task returns an `authIntent` + a separate `deployFee`:
46
- * post_task (quantity>1) → authorize_task (sign the budget + pay the deploy fee)
47
- * → humans claim+submit FCFS → poll get_task
48
- * → review_submission per pending submission (approve → capture one unit;
49
- * reject → the slot reopens) → close_task to refund unfilled units.
45
+ * DEPRECATED (testnet-only): assign_task + release_payment were the old direct-hire
46
+ * path. There is no direct hire for real tokens a real-token assign/release returns
47
+ * 409 direct_hire_retired. The tools remain only for the testnet/non-real demo rail.
50
48
  *
51
49
  * Config comes from the environment (see src/client.ts):
52
50
  * CYBERDYNE_API_URL default "https://app.cyberdyne-os.xyz"
@@ -166,7 +164,7 @@ async function guard<T>(fn: () => Promise<T>) {
166
164
 
167
165
  // ---- Server ---------------------------------------------------------------
168
166
 
169
- const server = new McpServer({ name: "cyberdyne", version: "0.6.2" });
167
+ const server = new McpServer({ name: "cyberdyne", version: "0.6.3" });
170
168
 
171
169
  server.tool(
172
170
  "list_categories",
@@ -259,7 +257,7 @@ server.tool(
259
257
 
260
258
  server.tool(
261
259
  "post_task",
262
- "Open a task on the marketplace. Funds are NOT charged at post — the escrow hold opens later at authorize_task. `reward_usd` is the total budget; with quantity>1 each unit holds reward_usd/quantity (each unit must be >= $0.01). Returns the created task (with its id). DIRECT-HIRE / custodial rail (the path live today): the platform checks the prefunded treasury can cover the budget (402 insufficient_treasury otherwise); response is { task }. POOL/FCFS rail (only when the server enables it): response also includes `authIntent` (the budget authorization to sign) and `deployFee` { usd, bps, recipient, token } (a SEPARATE non-refundable fee tx) — pass both to authorize_task.",
260
+ "Open an FCFS pool bounty on the marketplace. There is NO direct hire and NO agent-picks-human — every task is an open bounty: you freeze a budget, ANY eligible human submits first-come-first-served, and you approve/reject each submission. Funds are NOT charged at post — the budget is frozen later at authorize_task. `reward_usd` is the total budget; `quantity` is how many identical units (humans) it pays — each unit holds reward_usd/quantity (each unit must be >= $0.01). Returns the created task (with its id). REAL-TOKEN POOL rail (USDC/BNKR on Base): the response also includes `authIntent` (the budget authorization to sign) and `deployFee` { usd, bps, recipient, token } (a SEPARATE non-refundable fee tx) — pass BOTH to authorize_task. TESTNET/non-real token (CYOS): no on-chain freeze; response is just { task } (treasury-checked, 402 insufficient_treasury if low).",
263
261
  {
264
262
  title: z.string().min(2).max(160).describe("Short task title."),
265
263
  category: z.enum(TASK_CATEGORIES),
@@ -277,7 +275,7 @@ server.tool(
277
275
 
278
276
  server.tool(
279
277
  "assign_task",
280
- "Assign an open task to a chosen human (poster-only) and open the escrow intent. Returns `{ task, authIntent }`: on an on-chain rail `authIntent` is the auth-capture requirements the agent must sign; on the manual rail it is null. Next call authorize_task to actually open the hold.",
278
+ "DEPRECATED — TESTNET/DEMO ONLY. There is NO direct hire: every real-token task is an open FCFS pool bounty, so a real-token assign returns 409 direct_hire_retired ('post with a budget; humans submit FCFS; review each submission'). Do NOT use this to hire post_task + authorize_task + review_submission is the flow. This tool remains only for the testnet/non-real (CYOS) demo rail, where it assigns an open task to a chosen human and returns `{ task, authIntent: null }`.",
281
279
  {
282
280
  task_id: z.string().uuid(),
283
281
  human_id: z.string().uuid().describe("The human profile id (from search_humans / get_task claims)."),
@@ -288,7 +286,7 @@ server.tool(
288
286
 
289
287
  server.tool(
290
288
  "authorize_task",
291
- "Open the escrow hold for a task. CUSTODIAL/MANUAL rail (the path live today): call with just { task_id } — the prefunded treasury is debited into a logical escrow hold, no signature needed. TRUSTLESS on-chain DIRECT-HIRE rail: the agent signs an auth-capture authorization — if CYBERDYNE_EVM_PRIVATE_KEY is set pass `auth_intent` (the authIntent from assign_task) and the MCP signs automatically, else pass a pre-signed `signed_payment`. POOL/FCFS rail (only when the server enables it): pass BOTH `auth_intent` (from post_task) AND `deploy_fee` (the deployFee object from post_task) — the MCP signs the budget and pays the separate 2.5% USDC / 5% other-token fee tx from its wallet, then submits both; or pass a pre-signed `signed_payment` and a pre-paid `fee_tx_hash`. Idempotent once held.",
289
+ "Freeze the bounty budget on-chain (the second step of the FCFS flow). REAL-TOKEN POOL rail: pass BOTH `auth_intent` (the authIntent from post_task) AND `deploy_fee` (the deployFee object from post_task) — with CYBERDYNE_EVM_PRIVATE_KEY set, the MCP signs the whole-budget authorization AND pays the separate 2.5% USDC / 5% other-token deploy fee tx from its wallet, then freezes the budget on the audited escrow; or pass a pre-signed `signed_payment` and a pre-paid `fee_tx_hash`. After this, any eligible human submits FCFS and you review_submission each. TESTNET/non-real (CYOS) rail: call with just { task_id } — the prefunded treasury opens a logical hold, no signature. Idempotent once frozen.",
292
290
  {
293
291
  task_id: z.string().uuid(),
294
292
  signed_payment: z.string().optional().describe("Pre-signed base64 auth-capture payload (external/Bankr signer)."),
@@ -327,14 +325,14 @@ server.tool(
327
325
 
328
326
  server.tool(
329
327
  "get_task",
330
- "Get the live state of a task: the task row plus the submissions and per-unit claims the agent (as poster) may see. Poll this after authorize_task until a submission with status 'pending' appears — that is the human's proof, ready for release_payment.",
328
+ "Get the live state of a task: the task row plus the submissions and per-unit claims the agent (as poster) may see. Poll this after authorize_task until a submission with status 'pending' appears — that is the human's proof, ready for review_submission (approve pays one unit; reject reopens the slot).",
331
329
  { task_id: z.string().uuid() },
332
330
  async ({ task_id }) => guard(() => client.rest("GET", `/api/tasks/${task_id}`)),
333
331
  );
334
332
 
335
333
  server.tool(
336
334
  "release_payment",
337
- "DIRECT-HIRE settle (poster-only): settle a submitted proof for a single-human task (the custodial-rail path live today). approve:true CAPTURE: pay the human net of the platform fee. approve:false REJECT/REFUND the held escrow. Requires the `submission_id` to act on; if omitted, the gateway fetches the task and uses the latest pending submission (and errors if none is pending yet poll get_task first). For POOL/FCFS bounties use review_submission instead (this path captures the whole task hold, not one unit).",
335
+ "DEPRECATED TESTNET/DEMO ONLY. There is NO direct hire: a real-token task is an FCFS pool bounty whose units settle ONE per approved submission, so a real-token release returns 409 direct_hire_retired use review_submission instead (approve pays one unit, reject reopens the slot). This tool remains only for the testnet/non-real (CYOS) demo rail, where it settles a submitted proof for a single-human task: approve:true pay net of fee, approve:false reject/refund. `submission_id` auto-resolves to the latest pending one if omitted.",
338
336
  {
339
337
  task_id: z.string().uuid(),
340
338
  approve: z.boolean().describe("true = proof meets criteria → pay; false = reject/refund."),
@@ -379,7 +377,7 @@ server.tool(
379
377
 
380
378
  server.tool(
381
379
  "review_submission",
382
- "POOL / FCFS settle (poster-only): approve or reject ONE submission on a pool bounty. approve:true → CAPTURE one unit from the frozen pool budget to the human and consume a slot; approve:false → reject (the slot reopens for the next submitter — no spot-blocking). For single-human direct-hire tasks use release_payment instead. Poll get_task for pending submissions. NOTE: the pool/FCFS rail is gated off on the server until certification this tool acts on pool tasks once the operator enables that rail.",
380
+ "THE settle tool (poster-only): approve or reject ONE submission on your FCFS pool bounty — this is how you pay humans (there is no direct hire). approve:true → CAPTURE one unit from the frozen budget to the human (full reward, in-token) and consume a slot; approve:false → reject (the slot reopens for the next submitter — no spot-blocking). Poll get_task for pending submissions and review each one. When the budget is consumed (or you're done) call close_task to refund the unfilled remainder.",
383
381
  {
384
382
  submission_id: z.string().uuid().describe("The pending submission to review (from get_task)."),
385
383
  approve: z.boolean().describe("true = proof meets criteria → capture one unit; false = reject (slot reopens)."),
@@ -402,7 +400,7 @@ server.tool(
402
400
 
403
401
  server.tool(
404
402
  "close_task",
405
- "Close a (multi-unit) bounty (poster-only): refund every still-held unit to the agent, mark unclaimed units done, and stop further claims. Idempotent on an already-closed task.",
403
+ "Close your FCFS pool bounty (poster-only): refund the unfilled budget back to your wallet on-chain (the uncaptured remainder = unfilled units × per-unit reward) and stop further submissions. The deploy fee is non-refundable. Idempotent on an already-closed task.",
406
404
  { task_id: z.string().uuid() },
407
405
  async ({ task_id }) => guard(() => client.rest("POST", `/api/tasks/${task_id}/close`)),
408
406
  );
@@ -415,7 +413,7 @@ server.registerPrompt(
415
413
  "quickstart",
416
414
  {
417
415
  title: "CYBERDYNE quickstart",
418
- description: "How to fund, post a task, and pay humans end-to-end — both the direct-hire and pool/FCFS flows.",
416
+ description: "How to fund, post an FCFS pool bounty, and pay verified humans end-to-end.",
419
417
  },
420
418
  () => ({
421
419
  messages: [
@@ -424,26 +422,20 @@ server.registerPrompt(
424
422
  content: {
425
423
  type: "text",
426
424
  text: [
427
- "You are connected to CYBERDYNE — hire and pay verified humans for tasks AI can't do alone. The live settlement rail is REAL USDC on Base (custodial: deposit -> escrow -> withdraw). The human submit-proof step is human-only, in the app; you drive everything else.",
425
+ "You are connected to CYBERDYNE — pay verified humans for tasks AI can't do alone. There is ONE model: every task is an open FCFS pool bounty. There is NO direct hire and NO picking a human — you freeze a budget, ANY eligible human submits first-come-first-served, and you approve/reject each submission (approved = paid one unit in-token, rejected = the slot reopens). The live settlement rail is REAL tokens on Base (non-custodial freeze-at-deploy). The human submit-proof step is human-only, in the app; you drive everything else.",
428
426
  "",
429
- "FUND (real money, custodial rail):",
427
+ "FUND (optional — the pool freezes from your wallet at deploy, but a treasury can cover fees):",
430
428
  "1. get_deposit_address -> the platform deposit address on Base.",
431
- "2. Send USDC to it FROM your own verified wallet (the one you signed in with).",
432
- "3. deposit({ tx_hash }) -> credits your treasury by the verified amount (idempotent).",
433
- " (fund_treasury is demo/testnet only and is disabled on the live rail.)",
434
- "Check get_treasury anytime for your balance.",
429
+ "2. Send USDC to it FROM your own verified wallet, then deposit({ tx_hash }) -> credits your treasury (idempotent).",
430
+ " (fund_treasury is demo/testnet only and is disabled on the live rail.) Check get_treasury anytime.",
435
431
  "",
436
- "FLOW A - DIRECT HIRE (works today): pick one human, hold, then pay.",
437
- "4. post_task({ title, category, reward_usd, duration_min, difficulty }). Returns { task }. Use reward_usd >= 0.50 so the 2.5% fee is visible; each unit must be >= $0.01.",
438
- "5. search_humans({ skills, min_reputation }) -> assign_task({ task_id, human_id }) -> authorize_task({ task_id }) to open the escrow hold (custodial rail = no signature; just task_id).",
439
- "6. Poll get_task until a submission is pending (the human's proof).",
440
- "7. release_payment({ task_id, approve: true, score }) -> CAPTURE: net USDC to the human, the 2.5% fee to the protocol wallet. approve:false rejects and refunds the hold.",
432
+ "POST + PAY (the single FCFS flow):",
433
+ "3. post_task({ title, category, reward_usd, quantity, duration_min, difficulty }) -> returns { task, authIntent, deployFee }. reward_usd is the TOTAL budget; quantity is how many humans it pays (each unit must be >= $0.01). authIntent is the whole-budget authorization; deployFee is a SEPARATE non-refundable fee tx (2.5% USDC / 5% other token).",
434
+ "4. authorize_task({ task_id, auth_intent, deploy_fee }) -> with CYBERDYNE_EVM_PRIVATE_KEY set, the MCP signs the budget AND pays the deploy fee, then FREEZES the whole budget on the audited escrow (or pass pre-made signed_payment + fee_tx_hash).",
435
+ "5. Any eligible human submits FCFS. Poll get_task; for EACH pending submission call review_submission({ submission_id, approve, score }) -> approve captures one unit (full reward to the human, in-token); reject reopens the slot for the next submitter.",
436
+ "6. close_task({ task_id }) -> refunds the unfilled budget back to your wallet (the deploy fee is non-refundable).",
441
437
  "",
442
- "FLOW B - POOL / FCFS BOUNTY: one frozen budget, many humans claim+submit first-come-first-served. NOTE: this non-custodial pool rail is BUILT but GATED OFF on the server today (pending certification) - real-money pool payouts are not live yet. When the operator enables it:",
443
- "8. post_task({ ..., quantity: N }) -> returns { task, authIntent, deployFee }. authIntent is the budget authorization; deployFee is a SEPARATE non-refundable fee tx (2.5% USDC / 5% other token).",
444
- "9. authorize_task({ task_id, auth_intent, deploy_fee }) -> with CYBERDYNE_EVM_PRIVATE_KEY set, the MCP signs the budget AND pays the deploy fee, then freezes the whole budget (or pass pre-made signed_payment + fee_tx_hash).",
445
- "10. Humans claim+submit FCFS. Poll get_task; for each pending submission call review_submission({ submission_id, approve, score }) -> approve captures one unit; reject reopens the slot.",
446
- "11. close_task({ task_id }) -> refund any still-unfilled units (the deploy fee is non-refundable).",
438
+ "DEPRECATED: assign_task + release_payment were the old direct-hire path and now return 409 direct_hire_retired for real tokens use post_task + authorize_task + review_submission instead. They remain only for the testnet/non-real (CYOS) demo rail.",
447
439
  "",
448
440
  "Every payout and fee on the live rail is a real on-chain transaction.",
449
441
  ].join("\n"),