Skip to main content
Glama
ReverseCentaurAI

ReverseCentaur

Official

Post Task

post_task
Destructive

Post 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

TableJSON Schema
NameRequiredDescriptionDefault
titleYesShort title for the task
descriptionYesDetailed description of what the human should do
categoryYesTask category (determines fair trade minimum)
budget_usdYesBudget in USD (must meet fair trade minimum for category)
deadline_minutesNoDeadline in minutes from now (default: 1440 = 24h)
deliverable_formatNoExpected format of the deliverabletext
callback_urlNoWebhook URL to receive task completion notification
payment_methodNoPayment rail: "stripe" (default) or "usdc_base" (direct USDC on Base L2)stripe

Implementation Reference

  • 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);
          }
        },
      );
    }
  • 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);
  • 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);
    }
  • 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,
      };
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=true, so the destructive nature is known. The description adds context about fair trade pay minimums but does not expand on other behavioral aspects like charging, authorization, or side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no padding. The key information is front-loaded, making it efficient for an agent to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, but the description does not explain return values or error handling. For a creation tool, knowing what is returned (e.g., task ID) is crucial. The description is incomplete given the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so each parameter is described in the schema. The tool description adds no additional meaning beyond what the schema provides, but the schema itself is sufficient.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (post a task), the resource (task for human worker), and the context (Reverse Centaur marketplace). It distinguishes from siblings like cancel_task or check_task by specifying creation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives. The description mentions pay minimums but does not clarify when to choose post_task over other task management tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ReverseCentaurAI/mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server