Post Task
post_taskPost a task for a human worker on the Reverse Centaur marketplace. Set category, fair trade compliant budget, deadline, deliverable format, and payment method. Receive completion notification via webhook.
Instructions
Post a task for a human worker to complete via the Reverse Centaur Fair Trade marketplace. Tasks must meet category-specific fair trade pay minimums.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | Short title for the task | |
| description | Yes | Detailed description of what the human should do | |
| category | Yes | Task category (determines fair trade minimum) | |
| budget_usd | Yes | Budget in USD (must meet fair trade minimum for category) | |
| deadline_minutes | No | Deadline in minutes from now (default: 1440 = 24h) | |
| deliverable_format | No | Expected format of the deliverable | text |
| callback_url | No | Webhook URL to receive task completion notification | |
| payment_method | No | Payment rail: "stripe" (default) or "usdc_base" (direct USDC on Base L2) | stripe |
Implementation Reference
- src/tools/post-task.ts:9-102 (handler)Handler function that registers the 'post_task' tool. Calls the API client's postTask (or mock), formats the response with fee breakdown using computeChargeBreakdown and computeRoundUpSuggestion.
export function registerPostTask( server: McpServer, client: ApiClient | null, ): void { server.registerTool( 'post_task', { title: 'Post Task', description: 'Post a task for a human worker to complete via the Reverse Centaur Fair Trade marketplace. ' + 'Tasks must meet category-specific fair trade pay minimums.', inputSchema: z.object({ title: z.string().max(200).describe('Short title for the task'), description: z .string() .max(5000) .describe('Detailed description of what the human should do'), category: z .enum(TASK_CATEGORIES) .describe('Task category (determines fair trade minimum)'), budget_usd: z .number() .min(1) .describe('Budget in USD (must meet fair trade minimum for category)'), deadline_minutes: z .number() .int() .min(15) .max(43200) .optional() .default(1440) .describe('Deadline in minutes from now (default: 1440 = 24h)'), deliverable_format: z .enum(DELIVERABLE_FORMATS) .optional() .default('text') .describe('Expected format of the deliverable'), callback_url: z .string() .url() .optional() .describe('Webhook URL to receive task completion notification'), payment_method: z .enum(PAYMENT_METHODS) .optional() .default('stripe') .describe('Payment rail: "stripe" (default) or "usdc_base" (direct USDC on Base L2)'), }), annotations: { readOnlyHint: false, destructiveHint: true }, }, async (args) => { try { const result = client ? await client.postTask(args) : mockPostTask(args); const lines = [ `✅ Task posted: ${result.task_id}`, `Status: ${result.status}`, `Budget: $${result.budget_usd.toFixed(2)}`, `Fair trade minimum met: ${result.fair_trade_minimum_met}`, `Estimated match time: ${result.estimated_match_time_minutes} minutes`, `Deadline: ${result.deadline}`, ]; if (result.payment_method) { lines.push(`Payment method: ${result.payment_method}`); } // Full fee breakdown with processing fee pass-through const breakdown = computeChargeBreakdown(result.budget_usd); lines.push(`Total charge: $${breakdown.totalCharge.toFixed(2)}`); lines.push(` Processing (Stripe): $${breakdown.processingFee.toFixed(2)}`); lines.push(` Platform fee (15%): $${breakdown.platformFee.toFixed(2)}`); lines.push(` Worker earns: $${breakdown.workerPayout.toFixed(2)}`); const roundUp = computeRoundUpSuggestion(result.budget_usd); if (roundUp) { lines.push(''); lines.push(`Round up worker pay to $${roundUp.target_worker_payout_usd.toFixed(2)}? (+$${roundUp.additional_cost_usd.toFixed(2)} total)`); } return { content: [ { type: 'text' as const, text: lines.join('\n'), }, ], }; } catch (error) { return toolError(error); } }, ); } - src/types.ts:45-67 (schema)Type definitions for PostTaskInput and PostTaskResponse used by the handler and API client.
export interface PostTaskInput { title: string; description: string; category: TaskCategory; budget_usd: number; deadline_minutes?: number; deliverable_format?: DeliverableFormat; callback_url?: string; payment_method?: PaymentMethod; } export interface PostTaskResponse { task_id: string; status: 'posted'; budget_usd: number; fair_trade_minimum_met: true; estimated_match_time_minutes: number; deadline: string; created_at: string; payment_method?: PaymentMethod; worker_payout_usd?: number; platform_fee_usd?: number; } - src/server.ts:57-57 (registration)Registration call inside createServer that wires post_task into the MCP server.
registerPostTask(server, client); - src/api-client.ts:56-58 (helper)API client method that sends a POST /v1/tasks request with PostTaskInput body.
async postTask(input: PostTaskInput): Promise<PostTaskResponse> { return this.request<PostTaskResponse>('POST', '/v1/tasks', input); } - src/mock.ts:21-40 (helper)Mock implementation for local dev/testing that creates a fake task and returns a PostTaskResponse.
export function mockPostTask(input: PostTaskInput): PostTaskResponse { mockTaskCounter++; const taskId = `mock-task-${mockTaskCounter.toString().padStart(4, '0')}`; const now = new Date().toISOString(); const deadline = new Date( Date.now() + (input.deadline_minutes ?? 1440) * 60_000, ).toISOString(); mockTasks.set(taskId, { input, createdAt: now }); return { task_id: taskId, status: 'posted', budget_usd: input.budget_usd, fair_trade_minimum_met: true, estimated_match_time_minutes: 15, deadline, created_at: now, }; }