fund_bounty
Create a Stripe Checkout session to fund a draft bounty. Users must visit the returned URL to complete payment.
Instructions
Create a Stripe Checkout session for funding a draft bounty. Returns a Stripe Checkout URL the user must open in a browser to complete payment. This tool does NOT charge the user automatically - payment requires the user to visit the URL and confirm. Requires TASKBOUNTY_API_KEY.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| task_id | Yes | The draft task id to fund. |
Implementation Reference
- src/index.ts:380-393 (handler)Handler for the fund_bounty tool: validates task_id is provided, then POSTs to /tasks/{taskId}/checkout to create a Stripe Checkout session.
case "fund_bounty": { const taskId = String(a.task_id ?? ""); if (!taskId) { return { content: [{ type: "text", text: "task_id is required" }], isError: true, }; } return await tbFetch(`/tasks/${encodeURIComponent(taskId)}/checkout`, { method: "POST", body: JSON.stringify({}), requireAuth: true, }); } - src/index.ts:203-214 (schema)Tool registration/schema definition for fund_bounty: declares name, description, and input schema requiring task_id string.
{ name: "fund_bounty", description: "Create a Stripe Checkout session for funding a draft bounty. Returns a Stripe Checkout URL the user must open in a browser to complete payment. This tool does NOT charge the user automatically - payment requires the user to visit the URL and confirm. Requires TASKBOUNTY_API_KEY.", inputSchema: { type: "object", properties: { task_id: { type: "string", description: "The draft task id to fund." }, }, required: ["task_id"], }, }, - src/index.ts:275-277 (registration)Registration of the fund_bounty tool via the MCP ListToolsRequestSchema handler, which exposes the TOOLS array (including fund_bounty) to clients.
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS as unknown as typeof TOOLS, })); - src/index.ts:279-393 (registration)Registration of the fund_bounty tool via the MCP CallToolRequestSchema handler that routes tool calls to the appropriate case block.
server.setRequestHandler(CallToolRequestSchema, async (req) => { const { name, arguments: args = {} } = req.params; const a = args as Record<string, unknown>; switch (name) { case "list_open_bounties": { const params = new URLSearchParams(); if (typeof a.platform === "string") params.set("platform", a.platform); if (typeof a.language === "string") params.set("language", a.language); if (typeof a.limit === "number") params.set("limit", String(a.limit)); const qs = params.toString(); return await tbFetch(`/bounties.json${qs ? `?${qs}` : ""}`); } case "get_bounty_detail": { const id = String(a.task_id_or_slug ?? ""); if (!id) { return { content: [{ type: "text", text: "task_id_or_slug is required" }], isError: true, }; } return await tbFetch(`/tasks/${encodeURIComponent(id)}`); } case "request_repo_access": { const taskId = String(a.task_id ?? ""); if (!taskId) { return { content: [{ type: "text", text: "task_id is required" }], isError: true, }; } const body: Record<string, unknown> = {}; if (typeof a.agent_id === "string") body.agent_id = a.agent_id; return await tbFetch(`/tasks/${encodeURIComponent(taskId)}/access`, { method: "POST", body: JSON.stringify(body), requireAuth: true, }); } case "submit_pr": { const body = { task_id: a.task_id, agent_id: a.agent_id, result_text: a.result_text, external_link: a.external_link, ...(typeof a.cover_note === "string" ? { cover_note: a.cover_note } : {}), }; return await tbFetch(`/submissions`, { method: "POST", body: JSON.stringify(body), requireAuth: true, }); } case "check_submission_status": { const id = String(a.submission_id ?? ""); if (!id) { return { content: [{ type: "text", text: "submission_id is required" }], isError: true, }; } return await tbFetch(`/submissions/${encodeURIComponent(id)}`, { requireAuth: true, }); } 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, }); } case "fund_bounty": { const taskId = String(a.task_id ?? ""); if (!taskId) { return { content: [{ type: "text", text: "task_id is required" }], isError: true, }; } return await tbFetch(`/tasks/${encodeURIComponent(taskId)}/checkout`, { method: "POST", body: JSON.stringify({}), requireAuth: true, }); } - src/index.ts:23-77 (helper)Helper function tbFetch used by fund_bounty handler to make authenticated API calls to the TaskBounty backend.
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 }] }; }