rentahuman-mcp 2.0.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 +38 -0
- package/dist/serve.js +153 -16
- package/dist/types/index.d.ts +5 -1
- package/package.json +2 -2
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
|
@@ -854,10 +854,58 @@ Use \`create_bounty\` with \`dryRun=true\` first:
|
|
|
854
854
|
- Confirm the budget and evidence requirements
|
|
855
855
|
- Post only after the user approves the preview
|
|
856
856
|
|
|
857
|
+
### Writing a Great Bounty
|
|
858
|
+
|
|
859
|
+
Well-specified bounties attract better applicants and avoid disputes. Always set:
|
|
860
|
+
|
|
861
|
+
1. **Title + description** \u2014 a clear title (5\u2013200 chars) and a description more
|
|
862
|
+
detailed than the raw request. Expand a brief ask into a proper task spec.
|
|
863
|
+
Never put personal information (addresses, phone numbers, real names) in the
|
|
864
|
+
public description \u2014 share those privately in chat after acceptance.
|
|
865
|
+
2. **Definition of done** (\`completionCriteria\`) \u2014 specific, measurable
|
|
866
|
+
criteria for what counts as complete.
|
|
867
|
+
3. **Evidence** (\`evidenceTypes\` + \`evidenceCriteria\`) \u2014 always set both.
|
|
868
|
+
Rules of thumb:
|
|
869
|
+
- Anything physical/in-person: timestamped photos AND at least one short
|
|
870
|
+
video clip \u2014 still photos alone are easy to fake.
|
|
871
|
+
- Anything online: a live link PLUS a screenshot, because links can 404 or
|
|
872
|
+
get removed.
|
|
873
|
+
- Location-specific tasks: evidence must show the location (landmark,
|
|
874
|
+
storefront, street sign).
|
|
875
|
+
4. **Requirements + skills** \u2014 infer concrete qualifications from the task
|
|
876
|
+
(e.g. "own professional camera equipment", "comfortable being in public").
|
|
877
|
+
5. **Price** \u2014 fixed USD by default. Anchor to real-world freelancer rates for
|
|
878
|
+
the effort, location, urgency, and skill level. Underpriced bounties get
|
|
879
|
+
low-quality applicants.
|
|
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.
|
|
885
|
+
|
|
886
|
+
**Application screening (\`applicationDetails\`)** \u2014 standard application
|
|
887
|
+
bounties support pre-acceptance screening items: text questions, acknowledgment
|
|
888
|
+
checkboxes, file uploads, and one required \`live_video\` field whose label is a
|
|
889
|
+
script the applicant must record with the in-browser camera (pre-recorded files
|
|
890
|
+
are rejected server-side).
|
|
891
|
+
|
|
892
|
+
**Appearance-based bounties MUST include the live-video gate.** When the worker
|
|
893
|
+
appears on camera or their appearance/presence is part of the deliverable \u2014
|
|
894
|
+
sign holding, UGC, sponsored posts, on-camera video, brand-ambassador or
|
|
895
|
+
GTM/promo appearances \u2014 always include one required \`live_video\` item with a
|
|
896
|
+
label like: "Record a short video of yourself explaining, in 2 sentences, why
|
|
897
|
+
you'd be a great fit for this task." This gives the poster a real look at each
|
|
898
|
+
applicant before accepting. (Not applicable to direct-upload \`submissionMode\`
|
|
899
|
+
bounties, which don't support \`applicationDetails\`.)
|
|
900
|
+
|
|
901
|
+
Never use screening items to ask for passwords, OTP/2FA codes, API keys,
|
|
902
|
+
government IDs, bank details, exact home addresses, or other sensitive personal
|
|
903
|
+
information.
|
|
904
|
+
|
|
857
905
|
For the fully managed beta, pass \`aiManaged: true\` and the platform will recruit
|
|
858
906
|
and vet workers, review chat-delivered submissions, release approved payments,
|
|
859
907
|
refund unused budget, and produce a final report. Managed bounties require a
|
|
860
|
-
fixed USD price and 1\
|
|
908
|
+
fixed USD price and 1\u201350 spots and cannot use \`mode: 'auto'\`. Poll the bounty's
|
|
861
909
|
managed run or subscribe to \`run.report_ready\` for the finished work.
|
|
862
910
|
|
|
863
911
|
### Start a Conversation
|
|
@@ -1399,7 +1447,6 @@ function calculatePlatformFee(baseAmountCents) {
|
|
|
1399
1447
|
}
|
|
1400
1448
|
|
|
1401
1449
|
// ../contracts/src/schemas/requests/bounty.ts
|
|
1402
|
-
var BOUNTY_FIAT_CURRENCIES = ["USD", "EUR"];
|
|
1403
1450
|
var BountyLocationRequest = Schema5.Struct({
|
|
1404
1451
|
city: Schema5.optional(Schema5.String.pipe(Schema5.maxLength(100))),
|
|
1405
1452
|
state: Schema5.optional(Schema5.String.pipe(Schema5.maxLength(100))),
|
|
@@ -1555,7 +1602,7 @@ var CreateBountyRequest = Schema5.Struct({
|
|
|
1555
1602
|
description: BOUNTY_LOCATION_DESCRIPTION
|
|
1556
1603
|
}),
|
|
1557
1604
|
deadline: Schema5.optional(Schema5.String).annotations({
|
|
1558
|
-
description: "
|
|
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."
|
|
1559
1606
|
}),
|
|
1560
1607
|
estimatedHours: Schema5.Number.pipe(
|
|
1561
1608
|
Schema5.finite(),
|
|
@@ -1572,10 +1619,8 @@ var CreateBountyRequest = Schema5.Struct({
|
|
|
1572
1619
|
).annotations({
|
|
1573
1620
|
description: `Price in the specified currency (minimum $${BOUNTY_MIN_PRICE_USD})`
|
|
1574
1621
|
}),
|
|
1575
|
-
currency: Schema5.optional(
|
|
1576
|
-
|
|
1577
|
-
).annotations({
|
|
1578
|
-
description: "USD or EUR (default USD)"
|
|
1622
|
+
currency: Schema5.optional(Schema5.Literal("USD")).annotations({
|
|
1623
|
+
description: "USD (default and only supported bounty currency)"
|
|
1579
1624
|
}),
|
|
1580
1625
|
bountyKind: Schema5.optional(Schema5.Literal("one_shot")).annotations({
|
|
1581
1626
|
description: "Agent-facing bounty creation only supports one-shot bounties. Ongoing data-collection bounties use bountyKind='ongoing' but are admin-only through the REST API and are intentionally not exposed through MCP create_bounty."
|
|
@@ -1599,9 +1644,21 @@ var CreateBountyRequest = Schema5.Struct({
|
|
|
1599
1644
|
autoExpireGhosts: Schema5.optional(Schema5.Boolean).annotations({
|
|
1600
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."
|
|
1601
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
|
+
}),
|
|
1602
1656
|
keepApplicantsOnFill: Schema5.optional(Schema5.Boolean).annotations({
|
|
1603
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."
|
|
1604
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
|
+
}),
|
|
1605
1662
|
identityRequired: Schema5.optional(Schema5.Boolean).annotations({
|
|
1606
1663
|
description: "Require applicants to pass an identity check (government ID) before applying. Verified once per account and reused across bounties. Default false."
|
|
1607
1664
|
}),
|
|
@@ -1609,7 +1666,7 @@ var CreateBountyRequest = Schema5.Struct({
|
|
|
1609
1666
|
description: "Require applicants to pass an on-device microphone quality check (live recording scored for noise, clipping, Bluetooth-headset bandwidth, and DNSMOS speech quality) before applying. Applicants get up to 2 attempts; the result (pass/warn/fail plus scores) is visible to you on each application via get_bounty_applications. Default false."
|
|
1610
1667
|
}),
|
|
1611
1668
|
aiManaged: Schema5.optional(Schema5.Literal(true)).annotations({
|
|
1612
|
-
description: "BETA \u2014 fully AI-managed bounty. The platform recruits and vets workers, reviews their chat-delivered submissions against the description and completion criteria, releases payment for approved work, refunds unused budget to your wallet, and returns a final report (poll get_bounty's managed run or subscribe to the run.report_ready webhook). Requires fixed price in USD and 1-
|
|
1669
|
+
description: "BETA \u2014 fully AI-managed bounty. The platform recruits and vets workers, reviews their chat-delivered submissions against the description and completion criteria, releases payment for approved work, refunds unused budget to your wallet, and returns a final report (poll get_bounty's managed run or subscribe to the run.report_ready webhook). Requires fixed price in USD and 1-50 spots. Currently in beta \u2014 the API returns 403 managed_bounties_beta_disabled when unavailable."
|
|
1613
1670
|
}),
|
|
1614
1671
|
submissionMode: Schema5.optional(
|
|
1615
1672
|
Schema5.Literal(...BOUNTY_SUBMISSION_MODES)
|
|
@@ -1775,7 +1832,7 @@ var UpdateBountyRequest = Schema5.Struct({
|
|
|
1775
1832
|
description: "New estimated duration in hours (min 5 minutes = 0.083)"
|
|
1776
1833
|
}),
|
|
1777
1834
|
deadline: Schema5.optional(Schema5.String).annotations({
|
|
1778
|
-
description: "New
|
|
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."
|
|
1779
1836
|
}),
|
|
1780
1837
|
requirements: Schema5.optional(Schema5.Array(Schema5.String)).annotations({
|
|
1781
1838
|
description: "New requirements list"
|
|
@@ -1813,6 +1870,17 @@ var UpdateBountyRequest = Schema5.Struct({
|
|
|
1813
1870
|
autoExpireGhosts: Schema5.optional(Schema5.Boolean).annotations({
|
|
1814
1871
|
description: "When true (with responseWindowHours set), ghosting workers\u2019 seats are auto-released at the deadline and the listing reopens."
|
|
1815
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
|
+
}),
|
|
1816
1884
|
spotsAvailable: Schema5.optional(
|
|
1817
1885
|
Schema5.Number.pipe(
|
|
1818
1886
|
Schema5.int(),
|
|
@@ -1825,6 +1893,9 @@ var UpdateBountyRequest = Schema5.Struct({
|
|
|
1825
1893
|
keepApplicantsOnFill: Schema5.optional(Schema5.Boolean).annotations({
|
|
1826
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."
|
|
1827
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
|
+
}),
|
|
1828
1899
|
completionCriteria: Schema5.optional(
|
|
1829
1900
|
Schema5.String.pipe(Schema5.minLength(10), Schema5.maxLength(2e3))
|
|
1830
1901
|
).annotations({
|
|
@@ -2031,6 +2102,24 @@ var ExpireApplicationRequest = Schema5.Struct({
|
|
|
2031
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."
|
|
2032
2103
|
})
|
|
2033
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
|
+
});
|
|
2034
2123
|
var GetBountyRequest = Schema5.Struct({
|
|
2035
2124
|
bountyId: Schema5.String.annotations({
|
|
2036
2125
|
description: "The unique ID of the bounty"
|
|
@@ -2055,7 +2144,6 @@ import { Schema as Schema7 } from "effect";
|
|
|
2055
2144
|
|
|
2056
2145
|
// ../contracts/src/validation/qa-assignment-contract.ts
|
|
2057
2146
|
import { Either, Schema as Schema6 } from "effect";
|
|
2058
|
-
var QA_ASSIGNMENT_CONTRACT_VERSION = 1;
|
|
2059
2147
|
var QaAssignmentEligibilitySchema = Schema6.Struct({
|
|
2060
2148
|
id: Schema6.String,
|
|
2061
2149
|
label: Schema6.String,
|
|
@@ -2074,7 +2162,7 @@ var QaAssignmentCriterionSchema = Schema6.Struct({
|
|
|
2074
2162
|
origin: Schema6.optional(Schema6.Literal("owner"))
|
|
2075
2163
|
});
|
|
2076
2164
|
var QaAssignmentContractSchema = Schema6.Struct({
|
|
2077
|
-
version: Schema6.Literal(
|
|
2165
|
+
version: Schema6.Literal(1, 2),
|
|
2078
2166
|
eligibility: Schema6.Array(QaAssignmentEligibilitySchema),
|
|
2079
2167
|
task: Schema6.Struct({
|
|
2080
2168
|
targetUrl: Schema6.String,
|
|
@@ -2083,7 +2171,9 @@ var QaAssignmentContractSchema = Schema6.Struct({
|
|
|
2083
2171
|
}),
|
|
2084
2172
|
submission: Schema6.Struct({
|
|
2085
2173
|
evidenceMode: Schema6.Literal("photo", "video", "document"),
|
|
2086
|
-
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"))
|
|
2087
2177
|
})
|
|
2088
2178
|
});
|
|
2089
2179
|
|
|
@@ -2182,6 +2272,8 @@ var BountyPublicResponse = Schema7.Struct({
|
|
|
2182
2272
|
fundingMethod: Schema7.optional(Schema7.String),
|
|
2183
2273
|
identityRequired: Schema7.optional(Schema7.Boolean),
|
|
2184
2274
|
micCheckRequired: Schema7.optional(Schema7.Boolean),
|
|
2275
|
+
completionWindowHours: Schema7.optional(Schema7.Number),
|
|
2276
|
+
autoAccept: Schema7.optional(Schema7.Boolean),
|
|
2185
2277
|
requiredQualificationIds: Schema7.optional(Schema7.Array(Schema7.String)),
|
|
2186
2278
|
supportedCountries: Schema7.optional(Schema7.Array(Schema7.String)),
|
|
2187
2279
|
intakeClosedCountries: Schema7.optional(Schema7.Array(Schema7.String)),
|
|
@@ -2269,9 +2361,14 @@ var expireApplicationSpec = {
|
|
|
2269
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.",
|
|
2270
2362
|
input: ExpireApplicationRequest
|
|
2271
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
|
+
};
|
|
2272
2369
|
var updateBountySpec = {
|
|
2273
2370
|
name: "update_bounty",
|
|
2274
|
-
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,
|
|
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.",
|
|
2275
2372
|
input: UpdateBountyRequest
|
|
2276
2373
|
};
|
|
2277
2374
|
var cancelBountySpec = {
|
|
@@ -3143,10 +3240,14 @@ var handleCreateBounty = (args) => Effect9.gen(function* () {
|
|
|
3143
3240
|
currency,
|
|
3144
3241
|
spotsAvailable,
|
|
3145
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 },
|
|
3146
3246
|
requirements: params.requirements || [],
|
|
3147
3247
|
skillsNeeded: params.skillsNeeded || [],
|
|
3148
3248
|
identityRequired: params.identityRequired || false,
|
|
3149
3249
|
keepApplicantsOnFill: params.keepApplicantsOnFill || false,
|
|
3250
|
+
completionWindowHours: params.completionWindowHours ?? null,
|
|
3150
3251
|
requiredLinks: params.requiredLinks || [],
|
|
3151
3252
|
applicationDetails: screeningFields,
|
|
3152
3253
|
submissionMode: params.submissionMode || "application",
|
|
@@ -3193,6 +3294,7 @@ var handleCreateBounty = (args) => Effect9.gen(function* () {
|
|
|
3193
3294
|
price: params.price,
|
|
3194
3295
|
currency: params.currency || "USD",
|
|
3195
3296
|
...params.aiManaged !== void 0 ? { aiManaged: params.aiManaged } : {},
|
|
3297
|
+
...params.aiManaged ? {} : { autoAccept: params.autoAccept !== false },
|
|
3196
3298
|
status: "open",
|
|
3197
3299
|
applicationCount: 0,
|
|
3198
3300
|
viewCount: 0,
|
|
@@ -3200,6 +3302,7 @@ var handleCreateBounty = (args) => Effect9.gen(function* () {
|
|
|
3200
3302
|
micCheckRequired: params.micCheckRequired || false,
|
|
3201
3303
|
liveCaptureRequirement: params.liveCaptureRequirement,
|
|
3202
3304
|
keepApplicantsOnFill: params.keepApplicantsOnFill || false,
|
|
3305
|
+
...params.completionWindowHours !== void 0 ? { completionWindowHours: params.completionWindowHours } : {},
|
|
3203
3306
|
requiredLinks: params.requiredLinks || [],
|
|
3204
3307
|
applicationDetails: screeningFields,
|
|
3205
3308
|
submissionMode: params.submissionMode || "application",
|
|
@@ -3615,6 +3718,36 @@ var expireApplicationTool = toMcpTool(
|
|
|
3615
3718
|
return ok(result);
|
|
3616
3719
|
})
|
|
3617
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
|
+
);
|
|
3618
3751
|
var getBountyOutreachStatusTool = toMcpTool(
|
|
3619
3752
|
getBountyOutreachStatusSpec,
|
|
3620
3753
|
(params) => Effect9.gen(function* () {
|
|
@@ -3668,7 +3801,7 @@ var payEnterpriseBountyTool = toMcpTool(
|
|
|
3668
3801
|
var bountyTools = [
|
|
3669
3802
|
{
|
|
3670
3803
|
name: "create_bounty",
|
|
3671
|
-
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. 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-
|
|
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.",
|
|
3672
3805
|
inputSchema: toInputSchema(CreateBountyRequest),
|
|
3673
3806
|
handler: handleCreateBounty
|
|
3674
3807
|
},
|
|
@@ -3686,6 +3819,7 @@ var bountyTools = [
|
|
|
3686
3819
|
acceptApplicationTool,
|
|
3687
3820
|
rejectApplicationTool,
|
|
3688
3821
|
expireApplicationTool,
|
|
3822
|
+
decideExtensionTool,
|
|
3689
3823
|
getBountyOutreachStatusTool,
|
|
3690
3824
|
boostBountyOutreachTool,
|
|
3691
3825
|
payEnterpriseBountyTool
|
|
@@ -4650,7 +4784,7 @@ var CreateHumanizationRequest = Schema13.Struct({
|
|
|
4650
4784
|
Schema13.greaterThanOrEqualTo(BOUNTY_MIN_PRICE_USD * 100),
|
|
4651
4785
|
Schema13.lessThanOrEqualTo(MAX_PRICE_CENTS)
|
|
4652
4786
|
),
|
|
4653
|
-
currency: Schema13.optionalWith(Schema13.Literal("USD"
|
|
4787
|
+
currency: Schema13.optionalWith(Schema13.Literal("USD"), {
|
|
4654
4788
|
default: () => "USD"
|
|
4655
4789
|
}),
|
|
4656
4790
|
applicantScreening: Schema13.optional(
|
|
@@ -7680,7 +7814,10 @@ var req = createRequire(import.meta.url);
|
|
|
7680
7814
|
var { version } = req("../package.json");
|
|
7681
7815
|
var server = new Server(
|
|
7682
7816
|
{ name: "rentahuman-mcp", version },
|
|
7683
|
-
{
|
|
7817
|
+
{
|
|
7818
|
+
capabilities: { tools: {}, resources: {} },
|
|
7819
|
+
instructions: 'RentAHuman lets AI agents hire humans for real-world tasks. Before creating your first bounty, read the rentahuman://guide resource \u2014 especially the "Writing a Great Bounty" section covering definition of done, evidence requirements, pricing, application screening, and the required live-video application gate for appearance-based work (sign holding, UGC, sponsored posts, promo appearances).'
|
|
7820
|
+
}
|
|
7684
7821
|
);
|
|
7685
7822
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
7686
7823
|
const tools = await runtime.runPromise(
|
package/dist/types/index.d.ts
CHANGED
|
@@ -65,12 +65,14 @@ declare const CreateBountyRequest: Schema.Struct<{
|
|
|
65
65
|
estimatedHours: Schema.refine<number, Schema.filter<typeof Schema.Number>>;
|
|
66
66
|
priceType: Schema.Literal<["fixed", "hourly"]>;
|
|
67
67
|
price: Schema.refine<number, Schema.filter<typeof Schema.Number>>;
|
|
68
|
-
currency: Schema.optional<Schema.Literal<["USD"
|
|
68
|
+
currency: Schema.optional<Schema.Literal<["USD"]>>;
|
|
69
69
|
bountyKind: Schema.optional<Schema.Literal<["one_shot"]>>;
|
|
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.
|
|
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",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/node": "^25.9.5",
|
|
65
65
|
"tsup": "^8.5.1",
|
|
66
|
-
"tsx": "^4.23.
|
|
66
|
+
"tsx": "^4.23.12",
|
|
67
67
|
"typescript": "^5.9.3"
|
|
68
68
|
},
|
|
69
69
|
"engines": {
|