rentahuman-mcp 2.1.0 → 2.2.0

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/README.md CHANGED
@@ -277,6 +277,44 @@ Only workers whose profile country matches can apply or receive automatic
277
277
  outreach. The country gate still applies when remote work is allowed. Include a
278
278
  `city` for city-level targeting instead.
279
279
 
280
+ #### Completion deadline (auto-reassign)
281
+
282
+ The bounty-level `deadline` is the application cutoff. At or after that time,
283
+ the listing leaves discovery and rejects new applications and direct uploads;
284
+ it does not create a per-worker completion timer. Use `completionWindowHours`
285
+ for accepted work:
286
+
287
+ `create_bounty` and `update_bounty` accept `completionWindowHours` (number,
288
+ 1-720; `update_bounty` also accepts `null` to disable). When set, a worker who
289
+ confirms their seat must complete the task within that many hours. They get an
290
+ in-chat + email reminder at the half-way point; past the deadline the seat is
291
+ automatically released, the application is expired, escrow returns to your
292
+ funding source, and the listing reopens for other applicants.
293
+
294
+ Workers may request more time. Pending requests appear on
295
+ `get_bounty_applications` as `completionExtension` with `status: "requested"`
296
+ (an open request pauses the auto-release for up to 24 hours). Answer with the
297
+ `decide_extension_request` tool: `action: "approve"` grants the requested
298
+ hours, `"deny"` resumes the original deadline, and `"grant"` with `hours`
299
+ extends proactively — with or without an open request. For AI-managed bounties
300
+ `completionWindowHours` overrides the default 6-hour managed work window;
301
+ managed seats handle blockers through their own issue-report flow instead of
302
+ extension requests.
303
+
304
+ #### Automatic applicant review (autoAccept)
305
+
306
+ `create_bounty` and `update_bounty` accept `autoAccept` (boolean, default
307
+ true). When on, every new application is reviewed automatically: deterministic
308
+ checks always run (account standing, country eligibility, payout viability,
309
+ your blocklist), and an AI review runs only when the application contains
310
+ free-text screening answers that need judgment. Qualified applicants are
311
+ accepted (the standard worker-confirmation window still applies unless
312
+ `skipAcceptanceConfirmation` is set), clear mismatches are rejected with a
313
+ reason, and uncertain cases stay pending for your manual review via
314
+ `get_bounty_applications` + `accept_application`. Pass `autoAccept: false` to
315
+ review and accept every application yourself. Ignored on `aiManaged` bounties,
316
+ whose managed engine owns applicant review.
317
+
280
318
  #### Microphone quality requirement
281
319
 
282
320
  `create_bounty` and `update_bounty` accept `micCheckRequired` (boolean, default
package/dist/serve.js CHANGED
@@ -877,7 +877,11 @@ Well-specified bounties attract better applicants and avoid disputes. Always set
877
877
  5. **Price** \u2014 fixed USD by default. Anchor to real-world freelancer rates for
878
878
  the effort, location, urgency, and skill level. Underpriced bounties get
879
879
  low-quality applicants.
880
- 6. **Deadline** \u2014 always set one; it must be in the future.
880
+ 6. **Application cutoff** (\`deadline\`) \u2014 always set one; it must be in the
881
+ future. At the cutoff the listing leaves discovery and stops accepting new
882
+ applications or direct uploads. If accepted workers also need a time limit,
883
+ set \`completionWindowHours\`; that clock starts when each worker confirms
884
+ their seat.
881
885
 
882
886
  **Application screening (\`applicationDetails\`)** \u2014 standard application
883
887
  bounties support pre-acceptance screening items: text questions, acknowledgment
@@ -1598,7 +1602,7 @@ var CreateBountyRequest = Schema5.Struct({
1598
1602
  description: BOUNTY_LOCATION_DESCRIPTION
1599
1603
  }),
1600
1604
  deadline: Schema5.optional(Schema5.String).annotations({
1601
- description: "Deadline for task completion (ISO 8601 format)"
1605
+ description: "Application cutoff (ISO 8601 format). At or after this time, the listing is removed from discovery and no new applications or direct uploads are accepted. Use completionWindowHours for a post-acceptance completion deadline."
1602
1606
  }),
1603
1607
  estimatedHours: Schema5.Number.pipe(
1604
1608
  Schema5.finite(),
@@ -1640,9 +1644,21 @@ var CreateBountyRequest = Schema5.Struct({
1640
1644
  autoExpireGhosts: Schema5.optional(Schema5.Boolean).annotations({
1641
1645
  description: "When true (and responseWindowHours is set), a ghosting worker\u2019s seat is automatically released at the deadline: their application is expired, the seat is freed, and the listing reopens for other applicants."
1642
1646
  }),
1647
+ completionWindowHours: Schema5.optional(
1648
+ Schema5.Number.pipe(
1649
+ Schema5.int(),
1650
+ Schema5.greaterThanOrEqualTo(1),
1651
+ Schema5.lessThanOrEqualTo(720)
1652
+ )
1653
+ ).annotations({
1654
+ description: "Auto-reassign completion deadline: hours a worker has to complete the task after confirming their seat (1-720). Workers are reminded at half the window; when the deadline passes the seat is automatically released and the listing reopens for other applicants. Workers may request an extension, which you approve, deny, or replace with your own via POST /bounties/{id}/applications/{appId}/extension/decision. For AI-managed bounties this overrides the default 6-hour work window. Omit for no completion deadline."
1655
+ }),
1643
1656
  keepApplicantsOnFill: Schema5.optional(Schema5.Boolean).annotations({
1644
1657
  description: "When true, pending applicants are kept (not auto-rejected) once all seats fill, so you can reuse the applicant pool after reopening or adding seats. Default false."
1645
1658
  }),
1659
+ autoAccept: Schema5.optional(Schema5.Boolean).annotations({
1660
+ description: "Automatically review applicants as they apply. Deterministic checks (account standing, country eligibility, payout viability, your blocklist) always run; an AI review runs only when the application contains free-text screening answers that need judgment. Qualified applicants are accepted (the standard worker-confirmation window still applies unless skipAcceptanceConfirmation is set), clear mismatches are rejected with a reason, and uncertain cases stay pending for your manual review. Default true; pass false to review and accept every application yourself. Ignored for aiManaged bounties, whose managed engine owns applicant review."
1661
+ }),
1646
1662
  identityRequired: Schema5.optional(Schema5.Boolean).annotations({
1647
1663
  description: "Require applicants to pass an identity check (government ID) before applying. Verified once per account and reused across bounties. Default false."
1648
1664
  }),
@@ -1816,7 +1832,7 @@ var UpdateBountyRequest = Schema5.Struct({
1816
1832
  description: "New estimated duration in hours (min 5 minutes = 0.083)"
1817
1833
  }),
1818
1834
  deadline: Schema5.optional(Schema5.String).annotations({
1819
- description: "New deadline (ISO 8601 format, or null to remove)"
1835
+ description: "New application cutoff (ISO 8601 format). At or after this time, no new applications or direct uploads are accepted. This does not retime accepted workers; use completionWindowHours for future confirmed seats."
1820
1836
  }),
1821
1837
  requirements: Schema5.optional(Schema5.Array(Schema5.String)).annotations({
1822
1838
  description: "New requirements list"
@@ -1854,6 +1870,17 @@ var UpdateBountyRequest = Schema5.Struct({
1854
1870
  autoExpireGhosts: Schema5.optional(Schema5.Boolean).annotations({
1855
1871
  description: "When true (with responseWindowHours set), ghosting workers\u2019 seats are auto-released at the deadline and the listing reopens."
1856
1872
  }),
1873
+ completionWindowHours: Schema5.optional(
1874
+ Schema5.NullOr(
1875
+ Schema5.Number.pipe(
1876
+ Schema5.int(),
1877
+ Schema5.greaterThanOrEqualTo(1),
1878
+ Schema5.lessThanOrEqualTo(720)
1879
+ )
1880
+ )
1881
+ ).annotations({
1882
+ description: "Auto-reassign completion deadline in hours (1-720), or null to disable. Only affects seats confirmed after the edit \u2014 live per-worker deadlines are not re-timed."
1883
+ }),
1857
1884
  spotsAvailable: Schema5.optional(
1858
1885
  Schema5.Number.pipe(
1859
1886
  Schema5.int(),
@@ -1866,6 +1893,9 @@ var UpdateBountyRequest = Schema5.Struct({
1866
1893
  keepApplicantsOnFill: Schema5.optional(Schema5.Boolean).annotations({
1867
1894
  description: "When true, pending applicants are kept (not auto-rejected) once all seats fill, so you can draw from the same pool after reopening or adding seats. Default false."
1868
1895
  }),
1896
+ autoAccept: Schema5.optional(Schema5.Boolean).annotations({
1897
+ description: "Turn automatic applicant review on or off. When on, deterministic checks always run and an AI review runs only for free-text screening answers; qualified applicants are accepted, clear mismatches rejected, uncertain cases left pending. Applications received while off stay pending; toggling on affects future applications only. Ignored on aiManaged bounties."
1898
+ }),
1869
1899
  completionCriteria: Schema5.optional(
1870
1900
  Schema5.String.pipe(Schema5.minLength(10), Schema5.maxLength(2e3))
1871
1901
  ).annotations({
@@ -2072,6 +2102,24 @@ var ExpireApplicationRequest = Schema5.Struct({
2072
2102
  description: "Optional human-readable reason shown to the released worker (e.g. why the seat was reclaimed). Defaults to a generic no-activity explanation."
2073
2103
  })
2074
2104
  });
2105
+ var DecideExtensionRequest = Schema5.Struct({
2106
+ bountyId: Schema5.String.annotations({ description: "The bounty ID" }),
2107
+ applicationId: Schema5.String.annotations({
2108
+ description: "The accepted application whose completion deadline to decide"
2109
+ }),
2110
+ action: Schema5.Literal("approve", "deny", "grant").annotations({
2111
+ description: "'approve' grants the worker's open extension request, 'deny' declines it (the original deadline resumes), 'grant' extends by `hours` whether or not a request is open."
2112
+ }),
2113
+ hours: Schema5.optional(
2114
+ Schema5.Number.pipe(
2115
+ Schema5.int(),
2116
+ Schema5.greaterThanOrEqualTo(1),
2117
+ Schema5.lessThanOrEqualTo(720)
2118
+ )
2119
+ ).annotations({
2120
+ description: "Extension length in hours. Required for 'grant'; for 'approve' it is only the fallback when the request did not name an hour count."
2121
+ })
2122
+ });
2075
2123
  var GetBountyRequest = Schema5.Struct({
2076
2124
  bountyId: Schema5.String.annotations({
2077
2125
  description: "The unique ID of the bounty"
@@ -2096,7 +2144,6 @@ import { Schema as Schema7 } from "effect";
2096
2144
 
2097
2145
  // ../contracts/src/validation/qa-assignment-contract.ts
2098
2146
  import { Either, Schema as Schema6 } from "effect";
2099
- var QA_ASSIGNMENT_CONTRACT_VERSION = 1;
2100
2147
  var QaAssignmentEligibilitySchema = Schema6.Struct({
2101
2148
  id: Schema6.String,
2102
2149
  label: Schema6.String,
@@ -2115,7 +2162,7 @@ var QaAssignmentCriterionSchema = Schema6.Struct({
2115
2162
  origin: Schema6.optional(Schema6.Literal("owner"))
2116
2163
  });
2117
2164
  var QaAssignmentContractSchema = Schema6.Struct({
2118
- version: Schema6.Literal(QA_ASSIGNMENT_CONTRACT_VERSION),
2165
+ version: Schema6.Literal(1, 2),
2119
2166
  eligibility: Schema6.Array(QaAssignmentEligibilitySchema),
2120
2167
  task: Schema6.Struct({
2121
2168
  targetUrl: Schema6.String,
@@ -2124,7 +2171,9 @@ var QaAssignmentContractSchema = Schema6.Struct({
2124
2171
  }),
2125
2172
  submission: Schema6.Struct({
2126
2173
  evidenceMode: Schema6.Literal("photo", "video", "document"),
2127
- criteria: Schema6.Array(QaAssignmentCriterionSchema)
2174
+ criteria: Schema6.Array(QaAssignmentCriterionSchema),
2175
+ /** When 'required', every origin:'owner' criterion must be bound to video evidence at submission time. */
2176
+ checklistEvidence: Schema6.optional(Schema6.Literal("required"))
2128
2177
  })
2129
2178
  });
2130
2179
 
@@ -2223,6 +2272,8 @@ var BountyPublicResponse = Schema7.Struct({
2223
2272
  fundingMethod: Schema7.optional(Schema7.String),
2224
2273
  identityRequired: Schema7.optional(Schema7.Boolean),
2225
2274
  micCheckRequired: Schema7.optional(Schema7.Boolean),
2275
+ completionWindowHours: Schema7.optional(Schema7.Number),
2276
+ autoAccept: Schema7.optional(Schema7.Boolean),
2226
2277
  requiredQualificationIds: Schema7.optional(Schema7.Array(Schema7.String)),
2227
2278
  supportedCountries: Schema7.optional(Schema7.Array(Schema7.String)),
2228
2279
  intakeClosedCountries: Schema7.optional(Schema7.Array(Schema7.String)),
@@ -2310,9 +2361,14 @@ var expireApplicationSpec = {
2310
2361
  description: "Release a previously accepted seat when the worker has ghosted (no message or submission after being accepted). Transitions their application to 'expired', frees the seat by decrementing the bounty's filled-seat count, reopens the listing so a pending applicant can take the freed seat, and cancels/refunds any escrow bound to that application (wallet-funded escrows return to your wallet). The released worker is notified. Owner only; only works on 'accepted' applications.",
2311
2362
  input: ExpireApplicationRequest
2312
2363
  };
2364
+ var decideExtensionSpec = {
2365
+ name: "decide_extension_request",
2366
+ description: "Answer a worker's completion-deadline extension request on one of your bounties, or proactively extend a worker's deadline. Only meaningful when the bounty sets completionWindowHours. 'approve' grants the worker's requested hours, 'deny' declines (the original deadline resumes and the overdue seat will auto-release), 'grant' extends by `hours` with or without an open request. Pending requests appear on applications from get_bounty_applications as completionExtension with status 'requested'; an open request pauses the auto-release for up to 24 hours. Owner only.",
2367
+ input: DecideExtensionRequest
2368
+ };
2313
2369
  var updateBountySpec = {
2314
2370
  name: "update_bounty",
2315
- description: "Update ordinary one-shot bounty details. You can modify the title, description, price, deadline, location, requiredLinks, applicationDetails, lifecycleMessages, liveCaptureRequirement, reactivate hidden inactive bounties, and more. To target an entire country, pass location with an ISO country code and isRemoteAllowed=false while omitting city and state. Live capture and required-link requirements can only be changed before applications are received. applicationDetails may be changed after applications are received; existing applications keep their original answers, while future applications use the latest fields. applicationDetails are application detail items for standard application bounties only; blank rows are ignored, uploads are capped at 3 fields, acknowledgments at 5 fields, and camera-only live_video at 1 required field. lifecycleMessages can define auto-message templates for acceptance, rejection, and submission review transitions. Admin-only ongoing bounty settings are intentionally not exposed through MCP. You can also pause/unpause a bounty (status 'paused'/'open'), close an unassigned bounty and return its unused funding (status 'closed'), increase seats via spotsAvailable, and keep pending applicants on fill via keepApplicantsOnFill. Use cancel_bounty for cancellation and refund handling. Work completion and payment are system-managed from escrow and payout evidence; status 'completed' and 'paid' cannot be set directly.",
2371
+ description: "Update ordinary one-shot bounty details. You can modify the title, description, price, application-cutoff deadline, location, requiredLinks, applicationDetails, lifecycleMessages, liveCaptureRequirement, reactivate hidden inactive bounties, and more. The deadline stops new applications and direct uploads; completionWindowHours controls post-acceptance completion timing. To target an entire country, pass location with an ISO country code and isRemoteAllowed=false while omitting city and state. Live capture and required-link requirements can only be changed before applications are received. applicationDetails may be changed after applications are received; existing applications keep their original answers, while future applications use the latest fields. applicationDetails are application detail items for standard application bounties only; blank rows are ignored, uploads are capped at 3 fields, acknowledgments at 5 fields, and camera-only live_video at 1 required field. lifecycleMessages can define auto-message templates for acceptance, rejection, and submission review transitions. Admin-only ongoing bounty settings are intentionally not exposed through MCP. You can also pause/unpause a bounty (status 'paused'/'open'), close an unassigned bounty and return its unused funding (status 'closed'), increase seats via spotsAvailable, keep pending applicants on fill via keepApplicantsOnFill, and change the auto-reassign completion deadline via completionWindowHours (null disables; only affects seats confirmed after the edit), and toggle automatic applicant review via autoAccept (applications received while off stay pending; toggling on affects future applications only; ignored on aiManaged bounties). Use cancel_bounty for cancellation and refund handling. Work completion and payment are system-managed from escrow and payout evidence; status 'completed' and 'paid' cannot be set directly.",
2316
2372
  input: UpdateBountyRequest
2317
2373
  };
2318
2374
  var cancelBountySpec = {
@@ -3184,10 +3240,14 @@ var handleCreateBounty = (args) => Effect9.gen(function* () {
3184
3240
  currency,
3185
3241
  spotsAvailable,
3186
3242
  ...params.aiManaged !== void 0 ? { aiManaged: params.aiManaged } : {},
3243
+ // Default-on unless explicitly disabled; aiManaged bounties never
3244
+ // store the flag (the managed engine owns applicant review).
3245
+ ...params.aiManaged ? {} : { autoAccept: params.autoAccept !== false },
3187
3246
  requirements: params.requirements || [],
3188
3247
  skillsNeeded: params.skillsNeeded || [],
3189
3248
  identityRequired: params.identityRequired || false,
3190
3249
  keepApplicantsOnFill: params.keepApplicantsOnFill || false,
3250
+ completionWindowHours: params.completionWindowHours ?? null,
3191
3251
  requiredLinks: params.requiredLinks || [],
3192
3252
  applicationDetails: screeningFields,
3193
3253
  submissionMode: params.submissionMode || "application",
@@ -3234,6 +3294,7 @@ var handleCreateBounty = (args) => Effect9.gen(function* () {
3234
3294
  price: params.price,
3235
3295
  currency: params.currency || "USD",
3236
3296
  ...params.aiManaged !== void 0 ? { aiManaged: params.aiManaged } : {},
3297
+ ...params.aiManaged ? {} : { autoAccept: params.autoAccept !== false },
3237
3298
  status: "open",
3238
3299
  applicationCount: 0,
3239
3300
  viewCount: 0,
@@ -3241,6 +3302,7 @@ var handleCreateBounty = (args) => Effect9.gen(function* () {
3241
3302
  micCheckRequired: params.micCheckRequired || false,
3242
3303
  liveCaptureRequirement: params.liveCaptureRequirement,
3243
3304
  keepApplicantsOnFill: params.keepApplicantsOnFill || false,
3305
+ ...params.completionWindowHours !== void 0 ? { completionWindowHours: params.completionWindowHours } : {},
3244
3306
  requiredLinks: params.requiredLinks || [],
3245
3307
  applicationDetails: screeningFields,
3246
3308
  submissionMode: params.submissionMode || "application",
@@ -3656,6 +3718,36 @@ var expireApplicationTool = toMcpTool(
3656
3718
  return ok(result);
3657
3719
  })
3658
3720
  );
3721
+ var decideExtensionTool = toMcpTool(
3722
+ decideExtensionSpec,
3723
+ (params) => Effect9.gen(function* () {
3724
+ const identity2 = yield* Identity;
3725
+ const api = yield* ApiClient;
3726
+ const rateLimit = yield* RateLimit;
3727
+ const config = yield* McpConfig;
3728
+ yield* rateLimit.check("decide_extension_request");
3729
+ if (config.mockMode) {
3730
+ return ok({
3731
+ success: true,
3732
+ action: params.action,
3733
+ message: params.action === "deny" ? "Extension declined (mock)." : "Deadline extended (mock).",
3734
+ mode: "mock"
3735
+ });
3736
+ }
3737
+ const verification = yield* identity2.createVerification(
3738
+ `extension_decision:${params.bountyId}:${params.applicationId}`
3739
+ );
3740
+ const result = yield* api.post(
3741
+ `/bounties/${params.bountyId}/applications/${params.applicationId}/extension/decision`,
3742
+ {
3743
+ action: params.action,
3744
+ ...params.hours !== void 0 ? { hours: params.hours } : {},
3745
+ ...verification
3746
+ }
3747
+ );
3748
+ return ok(result);
3749
+ })
3750
+ );
3659
3751
  var getBountyOutreachStatusTool = toMcpTool(
3660
3752
  getBountyOutreachStatusSpec,
3661
3753
  (params) => Effect9.gen(function* () {
@@ -3709,7 +3801,7 @@ var payEnterpriseBountyTool = toMcpTool(
3709
3801
  var bountyTools = [
3710
3802
  {
3711
3803
  name: "create_bounty",
3712
- description: "Create a one-shot task bounty for humans to apply to. To target an entire country, pass location with an ISO country code and isRemoteAllowed=false while omitting city and state. **IMPORTANT: Always call with dryRun=true first** to preview the bounty. Dry-run `preview.fundingTotal` is the total funding requirement before any existing wallet balance is applied. Show that estimate to the operator before posting. Show the preview to the user and ask 'Here's your bounty \u2014 would you like to edit anything before posting?' Only call again with dryRun=false (or omitted) after the user confirms. **You MUST help the user define completionCriteria and evidenceTypes** \u2014 ask what 'done' looks like and what proof they need (text/data, photos, video, or links). For specialized standard-application tasks, configure applicationDetails so applicants provide application details before review. Blank rows are ignored; application upload fields are one file each and capped at 3 total; acknowledgment checkboxes are capped at 5 total and can be optional or required; and one required live_video field may contain a script applicants must record with the in-browser camera. For appearance-based bounties where the worker appears on camera or their presence is part of the deliverable (sign holding, UGC, sponsored posts, on-camera video, promo/GTM appearances), always include one required live_video field with a label asking the applicant to explain in two sentences why they are a good fit \u2014 this gates applications on a live self-recorded video so the poster sees each applicant before accepting. Do not ask for passwords, OTP/2FA codes, API keys, private keys, seed phrases, government IDs, bank/card details, exact home addresses, dates of birth, or other sensitive personal information. For direct-review collection bounties, use submissionMode='photo_upload', 'video_upload', or 'document_upload' with matching submission settings instead of applicationDetails. lifecycleMessages can define auto-message templates for acceptance, rejection, and submission review transitions. You can require applicants to provide specific links (LinkedIn, GitHub, resume, etc.) using the requiredLinks parameter. Requires RENTAHUMAN_API_KEY from the account owner. Standard accounts use available wallet balance first; if the wallet cannot cover the bounty, the response includes deposit_url and checkout_total (the hosted charge after wallet balance is applied) and the account owner must complete checkout before the bounty is visible. Supports multi-person bounties by setting spotsAvailable > 1. Ongoing data-collection programs are managed separately and cannot be created through this tool. Pass optional `idempotencyKey` to make this safe to retry (a replayed key returns the original result instead of duplicating). BETA: pass aiManaged: true to have the platform fully manage the bounty \u2014 automated recruiting, vetting, submission review, payment release, and a final report. Fixed price USD only, 1-50 spots. Poll the bounty's managed run or subscribe to run.report_ready for the finished work.",
3804
+ description: "Create a one-shot task bounty for humans to apply to. To target an entire country, pass location with an ISO country code and isRemoteAllowed=false while omitting city and state. **IMPORTANT: Always call with dryRun=true first** to preview the bounty. Dry-run `preview.fundingTotal` is the total funding requirement before any existing wallet balance is applied. Show that estimate to the operator before posting. Show the preview to the user and ask 'Here's your bounty \u2014 would you like to edit anything before posting?' Only call again with dryRun=false (or omitted) after the user confirms. **You MUST help the user define completionCriteria and evidenceTypes** \u2014 ask what 'done' looks like and what proof they need (text/data, photos, video, or links). For specialized standard-application tasks, configure applicationDetails so applicants provide application details before review. Blank rows are ignored; application upload fields are one file each and capped at 3 total; acknowledgment checkboxes are capped at 5 total and can be optional or required; and one required live_video field may contain a script applicants must record with the in-browser camera. For appearance-based bounties where the worker appears on camera or their presence is part of the deliverable (sign holding, UGC, sponsored posts, on-camera video, promo/GTM appearances), always include one required live_video field with a label asking the applicant to explain in two sentences why they are a good fit \u2014 this gates applications on a live self-recorded video so the poster sees each applicant before accepting. Do not ask for passwords, OTP/2FA codes, API keys, private keys, seed phrases, government IDs, bank/card details, exact home addresses, dates of birth, or other sensitive personal information. For direct-review collection bounties, use submissionMode='photo_upload', 'video_upload', or 'document_upload' with matching submission settings instead of applicationDetails. lifecycleMessages can define auto-message templates for acceptance, rejection, and submission review transitions. You can require applicants to provide specific links (LinkedIn, GitHub, resume, etc.) using the requiredLinks parameter. Requires RENTAHUMAN_API_KEY from the account owner. Standard accounts use available wallet balance first; if the wallet cannot cover the bounty, the response includes deposit_url and checkout_total (the hosted charge after wallet balance is applied) and the account owner must complete checkout before the bounty is visible. Supports multi-person bounties by setting spotsAvailable > 1. Set completionWindowHours (1-720) to give confirmed workers a completion deadline: overdue seats auto-release and reopen for other applicants; workers may request extensions you answer with decide_extension_request. Ongoing data-collection programs are managed separately and cannot be created through this tool. Pass optional `idempotencyKey` to make this safe to retry (a replayed key returns the original result instead of duplicating). Applicants are auto-reviewed by default (autoAccept, default true): deterministic checks always run and an AI review runs only for free-text screening answers \u2014 qualified applicants are accepted, clear mismatches rejected with a reason, uncertain cases left pending for manual review; pass autoAccept: false to review and accept every application yourself. BETA: pass aiManaged: true to have the platform fully manage the bounty \u2014 automated recruiting, vetting, submission review, payment release, and a final report. Fixed price USD only, 1-50 spots. Poll the bounty's managed run or subscribe to run.report_ready for the finished work.",
3713
3805
  inputSchema: toInputSchema(CreateBountyRequest),
3714
3806
  handler: handleCreateBounty
3715
3807
  },
@@ -3727,6 +3819,7 @@ var bountyTools = [
3727
3819
  acceptApplicationTool,
3728
3820
  rejectApplicationTool,
3729
3821
  expireApplicationTool,
3822
+ decideExtensionTool,
3730
3823
  getBountyOutreachStatusTool,
3731
3824
  boostBountyOutreachTool,
3732
3825
  payEnterpriseBountyTool
@@ -70,7 +70,9 @@ declare const CreateBountyRequest: Schema.Struct<{
70
70
  spotsAvailable: Schema.optional<Schema.filter<Schema.filter<typeof Schema.Number>>>;
71
71
  responseWindowHours: Schema.optional<Schema.filter<Schema.filter<typeof Schema.Number>>>;
72
72
  autoExpireGhosts: Schema.optional<typeof Schema.Boolean>;
73
+ completionWindowHours: Schema.optional<Schema.filter<Schema.filter<Schema.filter<typeof Schema.Number>>>>;
73
74
  keepApplicantsOnFill: Schema.optional<typeof Schema.Boolean>;
75
+ autoAccept: Schema.optional<typeof Schema.Boolean>;
74
76
  identityRequired: Schema.optional<typeof Schema.Boolean>;
75
77
  micCheckRequired: Schema.optional<typeof Schema.Boolean>;
76
78
  aiManaged: Schema.optional<Schema.Literal<[true]>>;
@@ -145,8 +147,10 @@ declare const UpdateBountyRequest: Schema.Struct<{
145
147
  micCheckRequired: Schema.optional<typeof Schema.Boolean>;
146
148
  responseWindowHours: Schema.optional<Schema.filter<Schema.filter<typeof Schema.Number>>>;
147
149
  autoExpireGhosts: Schema.optional<typeof Schema.Boolean>;
150
+ completionWindowHours: Schema.optional<Schema.NullOr<Schema.filter<Schema.filter<Schema.filter<typeof Schema.Number>>>>>;
148
151
  spotsAvailable: Schema.optional<Schema.filter<Schema.filter<Schema.filter<typeof Schema.Number>>>>;
149
152
  keepApplicantsOnFill: Schema.optional<typeof Schema.Boolean>;
153
+ autoAccept: Schema.optional<typeof Schema.Boolean>;
150
154
  completionCriteria: Schema.optional<Schema.filter<Schema.filter<typeof Schema.String>>>;
151
155
  evidenceTypes: Schema.optional<Schema.filter<Schema.Array$<Schema.Literal<["text", "photo", "video", "link"]>>>>;
152
156
  evidenceCriteria: Schema.optional<Schema.filter<typeof Schema.String>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rentahuman-mcp",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "MCP server for AI agents to browse and book humans on rentahuman.ai",
5
5
  "keywords": [
6
6
  "ai",