Skip to main content
Glama

create_bounty_draft

Create an unfunded draft bounty to specify task details, title, amount, and deadline, then fund it separately via Stripe checkout.

Instructions

Create a new bounty as an unfunded DRAFT. Returns task_id and slug. Bounty is created as DRAFT/UNFUNDED. Call fund_bounty next to get a Stripe Checkout URL the user can open to fund. Requires TASKBOUNTY_API_KEY.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
titleYesBounty title (5-200 chars).
short_summaryYesOne-line summary (10-500 chars).
descriptionYesFull bounty description (20-10000 chars).
categoryYesCategory, e.g. 'code', 'research', 'design'.
bounty_amountYesBounty amount in USD.
submission_deadlineYesISO 8601 deadline. Must be at least 7 days from now.
evaluation_criteriaNoOptional evaluation criteria.
expected_output_formatNoOptional expected output format.
github_repo_urlNoOptional GitHub repo URL for code tasks.
tagsNoOptional comma-separated tags.
platformNoOptional platform: 'general' or 'code'.
languageNoOptional language filter (e.g. 'typescript').

Implementation Reference

  • Handler for the 'create_bounty_draft' tool. Validates required fields (title, short_summary, description, category, bounty_amount, submission_deadline), then POSTs the payload to /api/v1/tasks to create an unfunded draft bounty. Optional fields (evaluation_criteria, expected_output_format, github_repo_url, tags, platform, language) are conditionally added to the body.
    case "create_bounty_draft": {
      const required = ["title", "short_summary", "description", "category", "bounty_amount", "submission_deadline"];
      for (const key of required) {
        if (a[key] === undefined || a[key] === null || a[key] === "") {
          return {
            content: [{ type: "text", text: `${key} is required` }],
            isError: true,
          };
        }
      }
      const body: Record<string, unknown> = {
        title: a.title,
        short_summary: a.short_summary,
        description: a.description,
        category: a.category,
        bounty_amount: a.bounty_amount,
        submission_deadline: a.submission_deadline,
      };
      if (typeof a.evaluation_criteria === "string") body.evaluation_criteria = a.evaluation_criteria;
      if (typeof a.expected_output_format === "string") body.expected_output_format = a.expected_output_format;
      if (typeof a.github_repo_url === "string") body.github_repo_url = a.github_repo_url;
      if (typeof a.tags === "string") body.tags = a.tags;
      if (typeof a.platform === "string") body.platform = a.platform;
      if (typeof a.language === "string") body.language = a.language;
      return await tbFetch(`/tasks`, {
        method: "POST",
        body: JSON.stringify(body),
        requireAuth: true,
      });
    }
  • Input schema definition for the 'create_bounty_draft' tool. Defines all properties (title, short_summary, description, category, bounty_amount, submission_deadline as required; evaluation_criteria, expected_output_format, github_repo_url, tags, platform, language as optional) and their types.
    {
      name: "create_bounty_draft",
      description:
        "Create a new bounty as an unfunded DRAFT. Returns task_id and slug. Bounty is created as DRAFT/UNFUNDED. Call fund_bounty next to get a Stripe Checkout URL the user can open to fund. Requires TASKBOUNTY_API_KEY.",
      inputSchema: {
        type: "object",
        properties: {
          title: { type: "string", description: "Bounty title (5-200 chars)." },
          short_summary: { type: "string", description: "One-line summary (10-500 chars)." },
          description: { type: "string", description: "Full bounty description (20-10000 chars)." },
          category: { type: "string", description: "Category, e.g. 'code', 'research', 'design'." },
          bounty_amount: { type: "number", description: "Bounty amount in USD." },
          submission_deadline: {
            type: "string",
            description: "ISO 8601 deadline. Must be at least 7 days from now.",
          },
          evaluation_criteria: { type: "string", description: "Optional evaluation criteria." },
          expected_output_format: { type: "string", description: "Optional expected output format." },
          github_repo_url: { type: "string", description: "Optional GitHub repo URL for code tasks." },
          tags: { type: "string", description: "Optional comma-separated tags." },
          platform: { type: "string", description: "Optional platform: 'general' or 'code'." },
          language: { type: "string", description: "Optional language filter (e.g. 'typescript')." },
        },
        required: [
          "title",
          "short_summary",
          "description",
          "category",
          "bounty_amount",
          "submission_deadline",
        ],
      },
    },
  • src/index.ts:270-277 (registration)
    The 'create_bounty_draft' tool is registered in the TOOLS array (line 79) which is exposed via the ListToolsRequestSchema handler (line 275-277). The CallToolRequestSchema handler (line 279) dispatches to the case statement on line 349.
    const server = new Server(
      { name: "taskbounty-mcp-server", version: "0.1.0" },
      { capabilities: { tools: {} } },
    );
    
    server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: TOOLS as unknown as typeof TOOLS,
    }));
  • The tbFetch helper function is used by the handler to make the POST request to /api/v1/tasks. It handles authentication via Bearer token, JSON content-type, and error responses.
    async function tbFetch(
      path: string,
      init: RequestInit & { requireAuth?: boolean } = {},
    ): Promise<ToolResult> {
      const { requireAuth, headers, ...rest } = init;
      if (requireAuth && !API_KEY) {
        return {
          content: [
            {
              type: "text",
              text: "Missing TASKBOUNTY_API_KEY environment variable. Set it to your tb_live_* key from https://www.task-bounty.com/dashboard/api-keys.",
            },
          ],
          isError: true,
        };
      }
      const url = `${API_BASE}${path}`;
      const finalHeaders: Record<string, string> = {
        Accept: "application/json",
        ...(headers as Record<string, string> | undefined),
      };
      if (API_KEY) finalHeaders["Authorization"] = `Bearer ${API_KEY}`;
      if (rest.body && !finalHeaders["Content-Type"]) {
        finalHeaders["Content-Type"] = "application/json";
      }
    
      let res: Response;
      try {
        res = await fetch(url, { ...rest, headers: finalHeaders });
      } catch (err) {
        return {
          content: [
            {
              type: "text",
              text: `Network error calling ${url}: ${err instanceof Error ? err.message : String(err)}`,
            },
          ],
          isError: true,
        };
      }
    
      const text = await res.text();
      if (!res.ok) {
        return {
          content: [
            {
              type: "text",
              text: `HTTP ${res.status} ${res.statusText} from ${url}\n\n${text}`,
            },
          ],
          isError: true,
        };
      }
      return { content: [{ type: "text", text }] };
    }
Behavior3/5

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

No annotations, so description carries burden. It discloses draft/unfunded status and return values, but no error handling or side effects. Adequate but not rich.

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?

Three sentences: purpose, next step, auth. Front-loaded and efficient with no wasted words.

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

Completeness3/5

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

Describes return values but no output schema. Missing error responses and behavior for edge cases. Moderately complete for a creation tool.

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 covers 100% of parameters with descriptions. Description adds no additional parameter info, so baseline 3 applies.

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?

Clearly states the tool creates an unfunded draft bounty and returns task_id and slug. Distinguishes from sibling tools like fund_bounty.

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

Usage Guidelines4/5

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

Explicitly instructs to call fund_bounty next and notes API key requirement. Lacks explicit when-not-to-use scenarios but provides clear next steps.

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/eliottreich/taskbounty-mcp-server'

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