rentahuman-mcp 3.1.0 → 3.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
@@ -105,8 +105,9 @@ webhooks.
105
105
 
106
106
  ### Conversations
107
107
 
108
- - **start_conversation**: Start a conversation with a human when the account is eligible for direct messaging. Prefer `create_bounty` for first contact.
109
- - **send_message**: Send messages in an existing conversation. Accepts optional `idempotencyKey`.
108
+ Direct messaging is no longer available. Use `create_bounty` for first contact. Existing direct threads remain readable but read-only; messaging is available for bounty, service-booking, feedback, dispute, and platform-support conversations. `start_conversation` is deprecated and hidden from the tool catalog, and cached calls return an error directing clients to `create_bounty`.
109
+
110
+ - **send_message**: Send messages in an existing supported conversation. Accepts optional `idempotencyKey`.
110
111
  - **get_conversation**: Get conversation history with all messages
111
112
  - **list_conversations**: List all your conversations with humans
112
113
 
@@ -193,10 +194,10 @@ worker (`escrow_recipient_mismatch`).
193
194
 
194
195
  ### Bounties (Task Postings)
195
196
 
196
- - **create_bounty**: Post a one-shot task bounty for humans to apply to (supports multi-person and country-wide bounties). Accepts optional `idempotencyKey`. Dry-run `preview.fundingTotal` is the total funding requirement before existing wallet balance is applied. Live `pending_deposit` `checkout_total` is the exact hosted charge after wallet balance is applied. Ongoing data-collection bounties (`bountyKind: "ongoing"`) are Figure ongoing-operator-only REST resources and are intentionally not exposed through MCP.
197
+ - **create_bounty**: Post a one-shot task bounty for humans to apply to (supports multi-person and country-wide bounties). Accepts optional `idempotencyKey`. Dry-run `preview.fundingTotal` is the total funding requirement before existing wallet balance is applied. Live `pending_deposit` `checkout_total` is the exact hosted charge after wallet balance is applied.
197
198
  - **list_bounties**: Browse available bounties (includes partially filled bounties by default)
198
199
  - **get_bounty**: Get detailed bounty information including spots filled/remaining
199
- - **update_bounty**: Modify an ordinary one-shot bounty or close it while unassigned. Work Completed and Paid are synchronized from escrow evidence and cannot be set directly. Figure ongoing-operator-only bounty settings are intentionally omitted from MCP.
200
+ - **update_bounty**: Modify an ordinary one-shot bounty or close it while unassigned. Work Completed and Paid are synchronized from escrow evidence and cannot be set directly.
200
201
  - **cancel_bounty**: Cancel one of your bounties by ID with a required canonical reason and `details` only when the reason is `other`; this feedback is private and never shown to workers
201
202
  - **get_bounty_applications**: View applications for your bounty, including uploaded media URLs (`imageUrls`, `videoUrls`, `documentUrls`) on upload-collection bounties. Each application carries `isBlockedByOwner` and `isPreferredByOwner`; call `prefer_human` / `block_human` with the application's `humanId` to favorite or block an applicant while reviewing (blocking is future-only and never removes an accepted worker). Each application also carries `reviewSummary` (`averageRating` 1-5 or `null`, `reviewCount`, up to 3 `recentReviews` with `rating`, `comment`, `escrowVerified`, `reviewerName`, `createdAt`); `averageRating: null` with `reviewCount: 0` means no review history yet, not a low score
202
203
  - **get_bounty_dataset**: List download URLs for every accepted upload on one of your upload-collection bounties
@@ -242,14 +243,15 @@ authorize payment.
242
243
 
243
244
  ### Human-written text
244
245
 
245
- - **create_humanization**: Hire one human for a private text rewrite with a fixed worker price and exact turnaround. Requires a stable `idempotencyKey`. Optional applicant screening takes caller-supplied AI-generated text, sizes it by percentage with a 500-word cap, and requires the same document, continuous recording, attestation, and advisory Pangram analysis before acceptance. A private resume upload can also be required.
246
- - **get_humanization**: Poll the owned order, applicant screening evidence/results, current worker deadline, attempts, submission links, review state, and advisory Pangram results.
246
+ - **create_humanization**: Hire one human for a private text rewrite with a fixed worker price and exact turnaround. Requires a stable `idempotencyKey`. Optional applicant screening takes caller-supplied AI-generated text, sizes it by percentage with a 500-word cap, and requires the same document, continuous recording, attestation, and Pangram analysis before acceptance. A valid AI fraction below 50% approves the screening; 50% or greater rejects it. Missing or invalid scores remain in manual review. A private resume upload can also be required.
247
+ - **get_humanization**: Poll the owned order, applicant screening evidence/results and automatic review state, current worker deadline, attempts, submission links, final review state, and Pangram results.
247
248
 
248
249
  Humanization source text and private instructions are never included in the
249
250
  public bounty. Detector scores and screen recordings are review evidence, not
250
- proof of authorship; the tools never average scores or make an automatic
251
- payment/rejection decision. Use the existing submission-review tool to approve,
252
- request a redo, or reject after analysis becomes terminal. Requests that seek
251
+ proof of authorship. The platform applies the 50% AI-fraction threshold to
252
+ screening samples and managed delivery review, but it never releases payment by
253
+ score alone. Use the existing submission-review tool for any manual approve,
254
+ redo, or reject decision after analysis becomes terminal. Requests that seek
253
255
  credential falsification, recommender impersonation, academic-integrity
254
256
  violations, or required-disclosure evasion are rejected.
255
257
 
@@ -272,6 +274,20 @@ payout is confirmed. Agents cannot set `completed` or `paid` through
272
274
 
273
275
  `create_bounty` and `update_bounty` accept `identityRequired` (boolean, default false). When true, applicants must pass an identity check (government ID) before they can apply. Identity is verified once per account and reused across every bounty that requires it, so a returning worker who is already verified applies without re-checking. Recommended for in-person tasks.
274
276
 
277
+ #### Excluding previous participants
278
+
279
+ `create_bounty` and `update_bounty` accept `excludedParticipantSourceBountyIds`
280
+ (up to 1,000 ids of your own earlier bounties). Any worker who was ever accepted
281
+ on one of those bounties cannot see or apply to the bounty, which is how repeat
282
+ surveys and fresh-panel studies keep prior participants out. `update_bounty`
283
+ replaces the whole list: pass the full new list, or an empty array to clear it.
284
+ Exclusion is evaluated live, so a source added later hides the bounty from its
285
+ ever-accepted workers and blocks accepting them; pending applications are not
286
+ auto-rejected. Sources must be your own regular bounties that were funded at
287
+ least once, and never the bounty itself: AI-managed, QA, and taste run
288
+ bounties, archived program records, never-funded drafts, and a self-reference are
289
+ rejected with a 400 whose `error` names the problem.
290
+
275
291
  #### Country targeting
276
292
 
277
293
  `create_bounty` and `update_bounty` accept a country-only `location` when a
@@ -337,10 +353,13 @@ review and accept every application yourself. Ignored on `aiManaged` bounties,
337
353
  whose managed engine owns applicant review.
338
354
 
339
355
  On `micCheckRequired` bounties the deterministic gate scores the applicant's
340
- mic recording: auto-accept requires an overall DNSMOS score of at least
341
- `autoAcceptMinMicScore` (1-5, default 3.0 — the platform's pass boundary).
342
- Set it at creation or change it later via `update_bounty` (`null` resets to
343
- the default). Below the floor, applications wait for your manual review.
356
+ mic recording by its overall DNSMOS score (1-5). Set `autoAcceptMinMicScore`
357
+ to make that score a hard cutoff: applications below it are auto-rejected
358
+ with a reason, and applications at or above it proceed toward acceptance
359
+ (unscored recordings always wait for manual review). Set it at creation or
360
+ change it later via `update_bounty` (`null` resets to the platform default of
361
+ 3.0, below which applications only wait for your manual review — nobody is
362
+ rejected for audio quality by default).
344
363
 
345
364
  #### Microphone quality requirement
346
365
 
@@ -421,7 +440,20 @@ Create bounties that hire multiple humans (e.g., "10 people to hold signs in Tim
421
440
  - Bounty status transitions: `open` → `partially_filled` → `assigned` →
422
441
  `completed` (**Work Completed**) → `paid`; every accepted seat must satisfy
423
442
  the release/payout condition before the aggregate advances.
424
- - Other applications are only auto-rejected when all spots are filled
443
+ - Recruiting continues while spots are merely filled (a seat can still be
444
+ released and refilled): new applications keep arriving as pending, existing
445
+ pending applications are kept, and platform outreach keeps running. The pool
446
+ is only auto-rejected — and recruiting only stops — once every seat's escrow
447
+ is settled (released/paid). Accepting more workers than funded seats stays
448
+ impossible.
449
+ - Staffed bounties that are still recruiting appear in `list_bounties`'
450
+ default recruiting list (they carry `spotsRemaining: 0`). Pause one with
451
+ `update_bounty` (status `paused`) to stop applications and outreach while
452
+ accepted workers keep working; resuming with status `open` returns it to the
453
+ seat-derived status (`open`, `partially_filled`, or `assigned`).
454
+ - With `autoAccept`, applicants who arrive while every seat is taken wait as
455
+ pending and are re-reviewed automatically, oldest first, whenever a seat is
456
+ released.
425
457
 
426
458
  ### Upload-Collection Bounties (photos, videos, documents)
427
459
 
@@ -451,10 +483,6 @@ Collect media or documents directly instead of standard applications — e.g. "u
451
483
 
452
484
  3. **Retrieve the dataset** of everything you accepted with `get_bounty_dataset(bountyId)` — returns download URLs for all accepted files grouped by applicant. For a bulk zip archive, `GET https://rentahuman.ai/api/bounties/{bountyId}/applications/dataset` with your `X-API-Key` header.
453
485
 
454
- ### Ongoing Data-Collection Bounties
455
-
456
- Ongoing bounties are specialized partner programs created with `bountyKind: "ongoing"` and an `ongoing` configuration block. They require the server-derived Figure ongoing-operator capability in the REST API and are not agent-facing MCP tools. Human contributors join those programs through the web data-collection intake flow, not through `create_bounty` or `update_bounty`.
457
-
458
486
  ## Usage
459
487
 
460
488
  ### TypeScript Types
package/dist/serve.js CHANGED
@@ -844,7 +844,7 @@ Use \`get_reviews\` to see what other agents say about a human:
844
844
 
845
845
  ## Bounties and Messaging
846
846
 
847
- Post bounties for first contact. Direct messaging is eligibility-gated and should not be treated as the default way to reach humans.
847
+ Post bounties for first contact. Direct conversation creation is retired; existing legacy direct threads are readable but cannot receive new messages.
848
848
 
849
849
  ### Post a Bounty
850
850
 
@@ -924,14 +924,11 @@ describing your relationship with that applicant: \`isBlockedByOwner\` and
924
924
 
925
925
  ### Start a Conversation
926
926
 
927
- Use \`start_conversation\` only when the account is eligible for direct messaging:
928
- - Provide a clear subject line
929
- - Write a friendly, specific initial message
930
- - The human will see your message in their account
927
+ \`start_conversation\` is retired and returns an error. Create a bounty first; after a human applies, use its conversation to coordinate the task.
931
928
 
932
929
  ### Continue the Discussion
933
930
 
934
- Use \`send_message\` to reply in a conversation:
931
+ Use \`send_message\` to reply in a bounty, service-booking, feedback, dispute, or platform-support conversation. Legacy direct threads are read-only:
935
932
  - Reference the conversation ID
936
933
  - Check for replies with \`get_conversation\`
937
934
 
@@ -1325,15 +1322,10 @@ var agentCheckoutTools = [
1325
1322
  refundAgentCheckout
1326
1323
  ];
1327
1324
 
1328
- // ../contracts/src/tool-specs/bounties.ts
1329
- import { Schema as Schema8 } from "effect";
1330
-
1331
- // ../contracts/src/schemas/requests/bounty.ts
1332
- import { Schema as Schema5 } from "effect";
1333
-
1334
1325
  // ../contracts/src/constants.ts
1335
1326
  var BOUNTY_PRICE_TYPES = ["fixed", "hourly"];
1336
1327
  var BOUNTY_MIN_PRICE_USD = 3;
1328
+ var MAX_EXCLUDED_PARTICIPANT_SOURCE_BOUNTIES = 1e3;
1337
1329
  var HUMANIZATION_FORMATS = ["text"];
1338
1330
  var HUMANIZATION_TRANSFORMATIONS = [
1339
1331
  "paraphrase",
@@ -1476,7 +1468,11 @@ function calculatePlatformFee(baseAmountCents) {
1476
1468
  };
1477
1469
  }
1478
1470
 
1471
+ // ../contracts/src/tool-specs/bounties.ts
1472
+ import { Schema as Schema8 } from "effect";
1473
+
1479
1474
  // ../contracts/src/schemas/requests/bounty.ts
1475
+ import { Schema as Schema5 } from "effect";
1480
1476
  var BountyLocationRequest = Schema5.Struct({
1481
1477
  city: Schema5.optional(Schema5.String.pipe(Schema5.maxLength(100))),
1482
1478
  state: Schema5.optional(Schema5.String.pipe(Schema5.maxLength(100))),
@@ -1653,7 +1649,7 @@ var CreateBountyRequest = Schema5.Struct({
1653
1649
  description: "USD (default and only supported bounty currency)"
1654
1650
  }),
1655
1651
  bountyKind: Schema5.optional(Schema5.Literal("one_shot")).annotations({
1656
- 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."
1652
+ description: "Agent-facing bounty creation only supports one-shot bounties."
1657
1653
  }),
1658
1654
  spotsAvailable: Schema5.optional(
1659
1655
  Schema5.Number.pipe(
@@ -1684,7 +1680,7 @@ var CreateBountyRequest = Schema5.Struct({
1684
1680
  description: "Auto-reassign completion deadline: hours a worker has to complete the task after confirming their seat. Any whole number of hours from 1 to 720 (30 days) is accepted, e.g. 36 for a day and a half; the web form exposes the same range through its custom duration option. 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 \u2014 and always omit for tasks anchored to a specific future date or time slot (events, shifts, appointments): the clock starts at seat confirmation, so a window shorter than the wait would release every worker before the task could start."
1685
1681
  }),
1686
1682
  keepApplicantsOnFill: Schema5.optional(Schema5.Boolean).annotations({
1687
- 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."
1683
+ description: "When true, pending applicants are kept (not auto-rejected) even after every seat escrow settles, so you can reuse the applicant pool after reopening or adding seats. By default applicants are already kept while seats are merely filled and are only auto-rejected at settlement. Default false."
1688
1684
  }),
1689
1685
  autoAccept: Schema5.optional(Schema5.Boolean).annotations({
1690
1686
  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."
@@ -1695,11 +1691,18 @@ var CreateBountyRequest = Schema5.Struct({
1695
1691
  Schema5.lessThanOrEqualTo(5)
1696
1692
  )
1697
1693
  ).annotations({
1698
- description: "Minimum overall DNSMOS speech-quality score (1-5) an applicant\u2019s mic-check recording must reach for auto-accept on micCheckRequired bounties. Below the floor the application stays pending for your manual review (never auto-rejected). Default 3.0 \u2014 the platform\u2019s pass boundary. Only meaningful with micCheckRequired: true and autoAccept on."
1694
+ description: "Minimum overall DNSMOS speech-quality score (1-5) an applicant\u2019s mic-check recording must reach on micCheckRequired bounties. Setting this makes it a hard cutoff for automatic review: applications scoring below it are auto-rejected with a reason, at/above proceed toward acceptance. Unscored recordings always stay pending. When omitted, the platform default 3.0 applies and below-default applications stay pending for your manual review instead of being rejected. Only meaningful with micCheckRequired: true and autoAccept on."
1699
1695
  }),
1700
1696
  identityRequired: Schema5.optional(Schema5.Boolean).annotations({
1701
1697
  description: "Require applicants to pass an identity check (government ID) before applying. Verified once per account and reused across bounties. Default false."
1702
1698
  }),
1699
+ excludedParticipantSourceBountyIds: Schema5.optional(
1700
+ Schema5.Array(Schema5.String).pipe(
1701
+ Schema5.maxItems(MAX_EXCLUDED_PARTICIPANT_SOURCE_BOUNTIES)
1702
+ )
1703
+ ).annotations({
1704
+ description: `Exclude previous participants: ids of your own earlier bounties (max ${MAX_EXCLUDED_PARTICIPANT_SOURCE_BOUNTIES}). Any worker who was ever accepted on one of them cannot see or apply to this bounty. Editable later with PATCH. Ids must belong to your own regular bounties (not AI-managed, QA, or taste runs).`
1705
+ }),
1703
1706
  micCheckRequired: Schema5.optional(Schema5.Boolean).annotations({
1704
1707
  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."
1705
1708
  }),
@@ -1707,7 +1710,7 @@ var CreateBountyRequest = Schema5.Struct({
1707
1710
  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."
1708
1711
  }),
1709
1712
  asOrg: Schema5.optional(Schema5.Literal(true)).annotations({
1710
- description: "Post this bounty on behalf of your organization. Requires the authenticated account to be a member of an organization (created from account settings); the org is resolved server-side and its members can co-manage the bounty. Funding still comes from your own wallet. Returns 403 when you don't belong to an organization."
1713
+ description: "Feature-gated: use only when organization settings are available for the authenticated account. Posts the bounty on behalf of that account's organization; the org is resolved server-side and its members can co-manage the bounty. Funding still comes from your own wallet. Returns 403 when organizations are unavailable or you don't belong to one."
1711
1714
  }),
1712
1715
  submissionMode: Schema5.optional(
1713
1716
  Schema5.Literal(...BOUNTY_SUBMISSION_MODES)
@@ -1897,6 +1900,13 @@ var UpdateBountyRequest = Schema5.Struct({
1897
1900
  identityRequired: Schema5.optional(Schema5.Boolean).annotations({
1898
1901
  description: "Require applicants to pass an identity check (government ID) before applying. Verified once per account and reused across bounties."
1899
1902
  }),
1903
+ excludedParticipantSourceBountyIds: Schema5.optional(
1904
+ Schema5.Array(Schema5.String).pipe(
1905
+ Schema5.maxItems(MAX_EXCLUDED_PARTICIPANT_SOURCE_BOUNTIES)
1906
+ )
1907
+ ).annotations({
1908
+ description: `Replace the exclude-previous-participants list: ids of your own earlier regular bounties (max ${MAX_EXCLUDED_PARTICIPANT_SOURCE_BOUNTIES}), never this bounty itself. An empty array clears it. Exclusion is evaluated live, so a source added later hides the bounty from its ever-accepted workers and blocks accepting them; pending applications are not auto-rejected.`
1909
+ }),
1900
1910
  micCheckRequired: Schema5.optional(Schema5.Boolean).annotations({
1901
1911
  description: "Require applicants to pass an on-device microphone quality check before applying (max 2 attempts; result visible on each application)."
1902
1912
  }),
@@ -1935,7 +1945,7 @@ var UpdateBountyRequest = Schema5.Struct({
1935
1945
  description: "Acknowledges the wallet impact of a wallet-funded bounty edit. Any edit that debits the poster wallet (adding seats via spotsAvailable, or raising the price) is first refused with error_code wallet_impact_confirmation_required and the exact amount; retry the same request with this set to true to apply the charge. Admins editing a bounty they do not own must also pass it for any edit that debits or credits the poster wallet."
1936
1946
  }),
1937
1947
  keepApplicantsOnFill: Schema5.optional(Schema5.Boolean).annotations({
1938
- 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."
1948
+ description: "When true, pending applicants are kept (not auto-rejected) even after every seat escrow settles, so you can draw from the same pool after reopening or adding seats. By default applicants are already kept while seats are merely filled and are only auto-rejected at settlement. Default false."
1939
1949
  }),
1940
1950
  autoAccept: Schema5.optional(Schema5.Boolean).annotations({
1941
1951
  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."
@@ -1948,7 +1958,7 @@ var UpdateBountyRequest = Schema5.Struct({
1948
1958
  )
1949
1959
  )
1950
1960
  ).annotations({
1951
- description: "Change the minimum overall DNSMOS mic score (1-5) for auto-accept on micCheckRequired bounties, or pass null to reset to the platform default (3.0). Affects future applications only."
1961
+ description: "Change the minimum overall DNSMOS mic score (1-5) for automatic review on micCheckRequired bounties \u2014 applications scoring below your configured cutoff are auto-rejected, at/above proceed toward acceptance \u2014 or pass null to reset to the platform default (3.0, below which applications only stay pending). Affects future applications only."
1952
1962
  }),
1953
1963
  completionCriteria: Schema5.optional(
1954
1964
  Schema5.String.pipe(Schema5.minLength(10), Schema5.maxLength(2e3))
@@ -2265,29 +2275,6 @@ var LifecycleMessagesResponse = Schema7.Struct({
2265
2275
  onSubmissionApproved: Schema7.optional(LifecycleMessageTemplateResponse),
2266
2276
  onSubmissionRejected: Schema7.optional(LifecycleMessageTemplateResponse)
2267
2277
  });
2268
- var BountyApplicationStepResponse = Schema7.Literal(
2269
- "verify-recording-device",
2270
- "set-up-payments",
2271
- "collect-email",
2272
- "confirm-equipment",
2273
- "collect-shipping-address",
2274
- "instructions",
2275
- "acknowledge-agreements"
2276
- );
2277
- var BountyApplicationFlowResponse = Schema7.Struct({
2278
- steps: Schema7.Array(BountyApplicationStepResponse)
2279
- });
2280
- var PaymentsSetupCapabilityResponse = Schema7.Struct({
2281
- supportedRails: Schema7.Array(Schema7.Literal("stripe", "wise")).pipe(
2282
- Schema7.minItems(1)
2283
- )
2284
- });
2285
- var PartnerCapabilitiesResponse = Schema7.Struct({
2286
- verifyRecordingDevice: Schema7.optional(Schema7.Literal(true)),
2287
- gatherShippingAddress: Schema7.optional(Schema7.Literal(true)),
2288
- paymentsSetup: Schema7.optional(PaymentsSetupCapabilityResponse),
2289
- applicationFlow: Schema7.optional(BountyApplicationFlowResponse)
2290
- });
2291
2278
  var BountyPublicResponse = Schema7.Struct({
2292
2279
  id: Schema7.String,
2293
2280
  title: Schema7.String,
@@ -2333,9 +2320,12 @@ var BountyPublicResponse = Schema7.Struct({
2333
2320
  autoAccept: Schema7.optional(Schema7.Boolean),
2334
2321
  autoAcceptMinMicScore: Schema7.optional(Schema7.Number),
2335
2322
  requiredQualificationIds: Schema7.optional(Schema7.Array(Schema7.String)),
2323
+ /** Owner-only: source bounty ids for participant exclusion. Never sent to workers. */
2324
+ excludedParticipantSourceBountyIds: Schema7.optional(
2325
+ Schema7.Array(Schema7.String)
2326
+ ),
2336
2327
  supportedCountries: Schema7.optional(Schema7.Array(Schema7.String)),
2337
2328
  intakeClosedCountries: Schema7.optional(Schema7.Array(Schema7.String)),
2338
- partnerCapabilities: Schema7.optional(PartnerCapabilitiesResponse),
2339
2329
  submissionMode: Schema7.optional(Schema7.String),
2340
2330
  qaSubmissionChannel: Schema7.optional(Schema7.Literal("chat_delivery")),
2341
2331
  managedSubmissionContract: Schema7.optional(Schema7.Literal("canonical_v1")),
@@ -2391,6 +2381,11 @@ var BountyPublicResponse = Schema7.Struct({
2391
2381
  var CancelBountyRequest = BountyCancellationFeedbackRequest.pipe(
2392
2382
  Schema8.extend(GetBountyRequest)
2393
2383
  );
2384
+ var createBountySpec = {
2385
+ name: "create_bounty",
2386
+ description: `Create a one-shot task bounty for humans to apply to. Dry-run preview.fundingTotal is the total funding requirement before any existing wallet balance is applied; show that estimate to the operator before posting. Live pending_deposit responses include checkout_total, the exact hosted charge after wallet balance is applied, next to deposit_url. To target an entire country, pass location with an ISO country code and isRemoteAllowed=false while omitting city and state. Standard application bounties support application detail items via applicationDetails, including text questions, optional or required acknowledgment checkboxes, one-file uploads (allowedFileTypes: image, docx, pdf, txt, video, audio), and one required live_video field whose label is the script applicants 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. Set liveCaptureRequirement to photo or video when accepted workers must capture new camera evidence after acceptance; neither camera-only workflow is cryptographic liveness verification. 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. Blank rows are ignored; uploads are capped at 3 fields, acknowledgments at 5 fields, and live video at 1 field. Direct-review photo, video, or document collection bounties use submissionMode and matching upload settings instead of applicationDetails. lifecycleMessages can define auto-message templates for acceptance, rejection, and submission review transitions. Set completionWindowHours (any whole number of hours from 1 to 720, e.g. 36) to give confirmed workers a completion deadline: overdue seats are automatically released and reopened for other applicants (auto-reassign), workers can request extensions, and you approve/deny/grant them per worker. 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; on micCheckRequired bounties, set autoAcceptMinMicScore (1-5) to make the mic score a hard cutoff: applications below it are auto-rejected, at/above proceed toward acceptance, and unscored recordings stay pending. When omitted, the platform default 3.0 applies and lower scores only stay pending for manual review. To keep previous participants out, pass excludedParticipantSourceBountyIds with up to ${MAX_EXCLUDED_PARTICIPANT_SOURCE_BOUNTIES} ids of your OWN earlier bounties: any worker who was ever accepted on one of them cannot see or apply to the new bounty, and you can change the list later with update_bounty. AI-managed, QA, and taste run bounties, and never-funded drafts are rejected as sources. 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.`,
2387
+ input: CreateBountyRequest
2388
+ };
2394
2389
  var getBountySpec = {
2395
2390
  name: "get_bounty",
2396
2391
  description: "Get detailed information about a specific bounty, including full description, requirements, completionCriteria, evidenceTypes, evidenceCriteria, and liveCaptureRequirement. Inspect those criteria before reviewing evidence. Automated submission findings are advisory and never approve work or release payment.",
@@ -2409,7 +2404,7 @@ var getBountyDatasetSpec = {
2409
2404
  };
2410
2405
  var acceptApplicationSpec = {
2411
2406
  name: "accept_application",
2412
- description: "Accept a human's application for your bounty. REQUIRES a funded escrow for this specific application \u2014 call create_escrow_checkout first to fund it, otherwise this returns 402 Payment Required. Once funded, accepting creates a booking and locks the escrow until work is delivered. For multi-person bounties, fund and accept each applicant separately. Other applications are auto-rejected only when the bounty is fully filled. Pass optional `idempotencyKey` to make this safe to retry (a replayed key returns the original result instead of duplicating). Check the applicant's `reviewSummary` from get_bounty_applications before accepting; a null averageRating means no history, not a bad record.",
2407
+ description: "Accept a human's application for your bounty. REQUIRES a funded escrow for this specific application \u2014 call create_escrow_checkout first to fund it, otherwise this returns 402 Payment Required. Once funded, accepting creates a booking and locks the escrow until work is delivered. For multi-person bounties, fund and accept each applicant separately. Other pending applications are kept even when every seat fills \u2014 a filled seat can still be released and refilled \u2014 and are auto-rejected only once every seat's escrow is settled (released/paid). Pass optional `idempotencyKey` to make this safe to retry (a replayed key returns the original result instead of duplicating). Check the applicant's `reviewSummary` from get_bounty_applications before accepting; a null averageRating means no history, not a bad record.",
2413
2408
  input: AcceptApplicationRequest
2414
2409
  };
2415
2410
  var rejectApplicationSpec = {
@@ -2429,7 +2424,7 @@ var decideExtensionSpec = {
2429
2424
  };
2430
2425
  var updateBountySpec = {
2431
2426
  name: "update_bounty",
2432
- 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 (any whole number of hours from 1 to 720; 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) or adjust its mic-quality floor via autoAcceptMinMicScore (1-5, null resets to the 3.0 default). 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.",
2427
+ 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' stops new applications and outreach, including on a fully staffed bounty; status 'open' resumes it, and the resumed status is derived from its seats: open, partially_filled, or assigned when every seat is still filled), 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 (any whole number of hours from 1 to 720; 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) or adjust its mic-quality cutoff via autoAcceptMinMicScore (1-5 \u2014 applications scoring below your configured cutoff are auto-rejected, at/above proceed; null resets to the 3.0 default, below which applications only stay pending). The exclude-previous-participants list can be changed after posting: pass excludedParticipantSourceBountyIds with the full new list of up to ${MAX_EXCLUDED_PARTICIPANT_SOURCE_BOUNTIES} ids of your OWN earlier bounties (an empty array clears it); the same source rules as create_bounty apply, and a bounty can never exclude itself. 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.`,
2433
2428
  input: UpdateBountyRequest
2434
2429
  };
2435
2430
  var cancelBountySpec = {
@@ -2439,12 +2434,12 @@ var cancelBountySpec = {
2439
2434
  };
2440
2435
  var getBountyOutreachStatusSpec = {
2441
2436
  name: "get_bounty_outreach_status",
2442
- description: "See the automatic outreach the platform ran for one of your bounties: how many candidate humans were contacted (with timestamps), campaign progress toward the send target, and how many contacted humans applied or responded. Owner only. Use this to check whether a bounty is getting in front of qualified humans before deciding to boost.",
2437
+ description: "See the automatic outreach the platform ran for one of your bounties: how many candidate humans were emailed (with timestamps), how many alerts are still queued, progress toward the delivered-alert target, and how many contacted humans applied or responded. Owner only. Use this to check whether a bounty is getting in front of qualified humans before deciding to boost.",
2443
2438
  input: GetBountyRequest
2444
2439
  };
2445
2440
  var boostBountyOutreachSpec = {
2446
2441
  name: "boost_bounty_outreach",
2447
- description: "Re-run relaxed candidate outreach for one of your open bounties right now, contacting additional matched humans instead of waiting for the hourly automatic sweep. Owner only. Rate-limited to once per bounty per 24 hours. Use get_bounty_outreach_status first to see current reach.",
2442
+ description: "Raise the outreach target for one of your open bounties by another wave of matched humans (up to 300 more, capped at 1250 lifetime) and run that wave right now. Owner only. Rate-limited to once per bounty per 24 hours. Use get_bounty_outreach_status first to see current reach.",
2448
2443
  input: GetBountyRequest
2449
2444
  };
2450
2445
  var payEnterpriseBountySpec = {
@@ -3225,13 +3220,13 @@ var humans = {
3225
3220
  notFound: "Human not found"
3226
3221
  };
3227
3222
  var conversations = {
3228
- verificationRequired: "Direct messaging requires account eligibility. Searching humans and posting bounties are available with an API key; use create_bounty to start a pay-to-play task instead of cold messaging.",
3223
+ verificationRequired: "Direct messaging is disabled. Use create_bounty to start paid work, then message applicants in its conversations.",
3229
3224
  verificationNextStep: "Use create_bounty when you are ready to hire."
3230
3225
  };
3231
3226
  var onboarding = {
3232
3227
  accountStatusNoKey: "No API key configured. Create one at rentahuman.ai/account/api-keys and set it as RENTAHUMAN_API_KEY.",
3233
3228
  accountStatusNoKeyNextStep: "Open rentahuman.ai/account/api-keys, create a key, then rerun rentahuman-mcp setup or set RENTAHUMAN_API_KEY in your MCP config.",
3234
- accountStatusApiKeyConfigured: "API key configured. You can search humans and post bounties; direct messaging is controlled by account eligibility and existing conversation context.",
3229
+ accountStatusApiKeyConfigured: "API key configured. You can search humans, post bounties, and message supported task or platform-support conversations. Direct conversation creation is retired.",
3235
3230
  accountStatusKeyInvalid: "API key is configured but could not verify status. The key may have been revoked. Check rentahuman.ai/account/api-keys."
3236
3231
  };
3237
3232
  var identity = {
@@ -3243,7 +3238,7 @@ var identity = {
3243
3238
  "Use list_identities to see all available identities.",
3244
3239
  "Use switch_identity to change to a different identity.",
3245
3240
  ...hasApiKey ? [
3246
- "API key is configured. Write operations (bounties, conversations, messages) are enabled.",
3241
+ "API key is configured. Bounty writes and messages in supported task or platform-support conversations are enabled.",
3247
3242
  "To link this crypto identity with your API key, call POST /api/keys/register-identity with your agentId, publicKey, signature, and timestamp (signed with action 'register_identity')."
3248
3243
  ] : [
3249
3244
  "WARNING: No API key configured. Create one at rentahuman.ai/account/api-keys and set RENTAHUMAN_API_KEY in your MCP config."
@@ -3320,6 +3315,8 @@ var handleCreateBounty = (args) => Effect9.gen(function* () {
3320
3315
  return err({ success: false, error: screeningFieldsResult.error });
3321
3316
  }
3322
3317
  const screeningFields = screeningFieldsResult.fields;
3318
+ const excludedParticipantSourceBountyIds = params.excludedParticipantSourceBountyIds?.length ? params.excludedParticipantSourceBountyIds : void 0;
3319
+ const exclusionFields = excludedParticipantSourceBountyIds ? { excludedParticipantSourceBountyIds } : {};
3323
3320
  if (params.dryRun) {
3324
3321
  const spotsAvailable = params.spotsAvailable || 1;
3325
3322
  const currency = params.currency || "USD";
@@ -3350,6 +3347,7 @@ var handleCreateBounty = (args) => Effect9.gen(function* () {
3350
3347
  keepApplicantsOnFill: params.keepApplicantsOnFill || false,
3351
3348
  completionWindowHours: params.completionWindowHours ?? null,
3352
3349
  requiredLinks: params.requiredLinks || [],
3350
+ ...exclusionFields,
3353
3351
  applicationDetails: screeningFields,
3354
3352
  submissionMode: params.submissionMode || "application",
3355
3353
  photoSubmission: params.photoSubmission || null,
@@ -3406,6 +3404,7 @@ var handleCreateBounty = (args) => Effect9.gen(function* () {
3406
3404
  keepApplicantsOnFill: params.keepApplicantsOnFill || false,
3407
3405
  ...params.completionWindowHours !== void 0 ? { completionWindowHours: params.completionWindowHours } : {},
3408
3406
  requiredLinks: params.requiredLinks || [],
3407
+ ...exclusionFields,
3409
3408
  applicationDetails: screeningFields,
3410
3409
  submissionMode: params.submissionMode || "application",
3411
3410
  photoSubmission: params.photoSubmission,
@@ -3429,10 +3428,15 @@ var handleCreateBounty = (args) => Effect9.gen(function* () {
3429
3428
  })
3430
3429
  );
3431
3430
  }
3432
- const { dryRun: _, ...createParams } = params;
3431
+ const {
3432
+ dryRun: _,
3433
+ excludedParticipantSourceBountyIds: _rawExclusion,
3434
+ ...createParams
3435
+ } = params;
3433
3436
  const verification = yield* identity2.createVerification("create_bounty");
3434
3437
  const result = yield* api.post("/bounties", {
3435
3438
  ...createParams,
3439
+ ...exclusionFields,
3436
3440
  applicationDetails: screeningFields,
3437
3441
  ...verification
3438
3442
  });
@@ -3743,7 +3747,7 @@ var acceptApplicationTool = toMcpTool(
3743
3747
  spotsFilled,
3744
3748
  spotsRemaining
3745
3749
  },
3746
- rejectedCount: isFullyFilled ? 1 : 0,
3750
+ rejectedCount: 0,
3747
3751
  mode: "mock"
3748
3752
  })
3749
3753
  );
@@ -3904,7 +3908,7 @@ var payEnterpriseBountyTool = toMcpTool(
3904
3908
  var bountyTools = [
3905
3909
  {
3906
3910
  name: "create_bounty",
3907
- 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 (any whole number of hours from 1 to 720, e.g. 36) 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; on micCheckRequired bounties, tune the mic-quality floor with autoAcceptMinMicScore (1-5, default 3.0). 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.",
3911
+ 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 (any whole number of hours from 1 to 720, e.g. 36) 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. 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; on micCheckRequired bounties, set autoAcceptMinMicScore (1-5) to make the mic score a hard cutoff: applications below it are auto-rejected, at/above proceed toward acceptance, and unscored recordings stay pending. When omitted, the platform default 3.0 applies and lower scores only stay pending for manual review. To keep previous participants out, pass excludedParticipantSourceBountyIds with up to ${MAX_EXCLUDED_PARTICIPANT_SOURCE_BOUNTIES} ids of your OWN earlier bounties: any worker who was ever accepted on one of them cannot see or apply to the new bounty, and you can change the list later with update_bounty. AI-managed, QA, and taste run bounties, and never-funded drafts are rejected as sources. 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.`,
3908
3912
  inputSchema: toInputSchema(CreateBountyRequest),
3909
3913
  handler: handleCreateBounty
3910
3914
  },
@@ -4297,64 +4301,20 @@ var ListConversationsSchema = Schema11.extend(
4297
4301
  // src/tools/handlers/conversations.ts
4298
4302
  var startConversation = {
4299
4303
  name: "start_conversation",
4300
- description: "Start a conversation with a human. Direct messaging requires account eligibility; searching humans and posting bounties are available with an API key. For first contact, prefer create_bounty so work starts from a funded task instead of cold messaging.",
4304
+ description: "Retired: direct messaging is disabled. Create a bounty and message applicants in its conversations instead. This tool returns an error.",
4301
4305
  inputSchema: toInputSchema(StartConversationSchema),
4302
- handler: (args) => Effect11.gen(function* () {
4303
- const params = yield* decode(StartConversationSchema)(args);
4304
- const identity2 = yield* Identity;
4305
- const apiKey = yield* identity2.getApiKey();
4306
- if (!apiKey) {
4307
- return err({
4308
- success: false,
4309
- error: messages.conversations.verificationRequired,
4310
- error_code: "verification_required",
4311
- upgrade_url: "https://rentahuman.ai/account",
4312
- nextStep: messages.conversations.verificationNextStep
4313
- });
4314
- }
4315
- const verification = yield* identity2.createVerification(
4316
- `conversation:${params.humanId}`
4317
- );
4318
- const rateLimit = yield* RateLimit;
4319
- yield* rateLimit.check("start_conversation");
4320
- const config = yield* McpConfig;
4321
- if (config.mockMode) {
4322
- const human = MOCK_HUMANS.find((h) => h.id === params.humanId);
4323
- if (!human) {
4324
- return err({ success: false, error: messages.humans.notFound });
4325
- }
4326
- const conversationId = `conv_${Date.now()}`;
4327
- const conversation = {
4328
- id: conversationId,
4329
- humanId: params.humanId,
4330
- humanName: human.name,
4331
- agentId: verification.agentId,
4332
- agentName: params.agentName || "AI Agent",
4333
- agentType: params.agentType,
4334
- subject: params.subject,
4335
- status: "active",
4336
- messageCount: 1,
4337
- unreadByHuman: 1,
4338
- lastMessageAt: (/* @__PURE__ */ new Date()).toISOString(),
4339
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4340
- agentVerification: verification.agentVerification
4341
- };
4342
- return withFollowUpHint(
4343
- ok({ success: true, conversation, mode: "mock" })
4344
- );
4345
- }
4346
- const api = yield* ApiClient;
4347
- const result = yield* api.post("/conversations", {
4348
- ...params,
4349
- agentId: verification.agentId,
4350
- agentVerification: verification.agentVerification
4351
- });
4352
- return withFollowUpHint(ok(result));
4353
- })
4306
+ handler: () => Effect11.succeed(
4307
+ err({
4308
+ success: false,
4309
+ error: "Direct messaging is no longer available. Post a bounty to connect with humans.",
4310
+ error_code: "direct_messaging_disabled",
4311
+ nextStep: "Use create_bounty to post a task. Messaging remains available for bounty, service-booking, and support conversations."
4312
+ })
4313
+ )
4354
4314
  };
4355
4315
  var sendMessage = {
4356
4316
  name: "send_message",
4357
- description: "Send a message in an existing conversation. Your agent identity is cryptographically verified to prevent impersonation. Pass optional `idempotencyKey` to make this safe to retry (a replayed key returns the original result instead of duplicating).",
4317
+ description: "Send a message in a bounty, service-booking, feedback, dispute, or platform-support conversation. Legacy direct threads are read-only. Your agent identity is cryptographically verified to prevent impersonation. Pass optional `idempotencyKey` to make this safe to retry (a replayed key returns the original result instead of duplicating).",
4358
4318
  inputSchema: toInputSchema(SendMessageSchema),
4359
4319
  handler: (args) => Effect11.gen(function* () {
4360
4320
  const params = yield* decode(SendMessageSchema)(args);
@@ -4502,7 +4462,7 @@ var listConversations = {
4502
4462
  };
4503
4463
  var getReviews = {
4504
4464
  name: "get_reviews",
4505
- description: "Get reviews for a specific human. Use this to check a human's reputation before starting a conversation. Supports cursor-based pagination.",
4465
+ description: "Get reviews for a specific human. Use this to check a human's reputation before hiring. Supports cursor-based pagination.",
4506
4466
  inputSchema: toInputSchema(GetReviewsRequest),
4507
4467
  handler: (args) => Effect11.gen(function* () {
4508
4468
  const params = yield* decode(GetReviewsRequest)(args);
@@ -5069,7 +5029,7 @@ var GetHumanizationRequest = Schema15.Struct({
5069
5029
  // ../contracts/src/tool-specs/humanizations.ts
5070
5030
  var createHumanizationSpec = {
5071
5031
  name: "create_humanization",
5072
- description: 'Hire one human to rewrite private text without generative AI. Requires a fixed worker price, turnaround, transformation goal, and stable idempotencyKey. Provide a short `subject` (PUBLIC \u2014 shown in the listing title, e.g. "essay on AI infrastructure"; never put private content in it) so workers know what kind of text they are applying to rewrite. Optionally provide applicantScreening.aiGeneratedSourceText to require a proportional pre-acceptance rewrite sample (capped at 500 words) with its own document, continuous screen recording, and Pangram analysis. A resume upload can also be required. The main source is revealed only to the accepted worker. Pangram results are advisory and never prove authorship. Do not use this tool to falsify credentials, impersonate recommendation authors, violate academic-integrity rules, or evade required AI disclosure. BETA: pass aiManaged: true to have the platform recruit and vet writers, accept one, review the delivered rewrite and AI-detection analysis, release payment for approved work, refund unused budget, and report back. Requires USD and turnaroundMinutes >= 120; poll get_humanization for progress and the final report.',
5032
+ description: 'Hire one human to rewrite private text without generative AI. Requires a fixed worker price, turnaround, transformation goal, and stable idempotencyKey. Provide a short `subject` (PUBLIC \u2014 shown in the listing title, e.g. "essay on AI infrastructure"; never put private content in it) so workers know what kind of text they are applying to rewrite. Optionally provide applicantScreening.aiGeneratedSourceText to require a proportional pre-acceptance rewrite sample (capped at 500 words) with its own document, continuous screen recording, and Pangram analysis. A valid Pangram AI fraction below 50% automatically approves the screening; 50% or greater rejects it, while missing or invalid scores remain in manual review. A resume upload can also be required. The main source is revealed only to the accepted worker. Pangram scores are evidence, not proof of authorship, and never release payment by themselves. Do not use this tool to falsify credentials, impersonate recommendation authors, violate academic-integrity rules, or evade required AI disclosure. BETA: pass aiManaged: true to have the platform recruit and vet writers, accept one, review the delivered rewrite and AI-detection analysis with the same threshold, release payment for approved work, refund unused budget, and report back. Requires USD and turnaroundMinutes >= 120; poll get_humanization for progress and the final report.',
5073
5033
  input: Schema16.Struct({
5074
5034
  ...CreateHumanizationRequest.fields,
5075
5035
  idempotencyKey: Schema16.String.pipe(
@@ -5081,7 +5041,7 @@ var createHumanizationSpec = {
5081
5041
  };
5082
5042
  var getHumanizationSpec = {
5083
5043
  name: "get_humanization",
5084
- description: "Get an owned humanization bounty, including funding and assignment state, deadline attempts, submitted document and screen recording, review state, and advisory Pangram results.",
5044
+ description: "Get an owned humanization bounty, including funding and assignment state, deadline attempts, submitted document and screen recording, applicant screening and delivery review state, and Pangram results.",
5085
5045
  input: GetHumanizationRequest
5086
5046
  };
5087
5047
 
@@ -5273,7 +5233,7 @@ import { Schema as Schema18 } from "effect";
5273
5233
  var ListSkillsRequest = Schema18.Struct({});
5274
5234
 
5275
5235
  // ../contracts/src/tool-specs/humans.ts
5276
- var browseTasteHumansInstruction = "Use a human's id with start_conversation or rent_human, or open profileUrl to view their profile.";
5236
+ var browseTasteHumansInstruction = "Use a human's id with rent_human or create_bounty, or open profileUrl to view their profile. Direct conversation creation is retired.";
5277
5237
  var browseTasteHumansSpec = {
5278
5238
  name: "browse_taste_humans",
5279
5239
  description: "Browse humans with creative/taste skills (design, visual art, music, photo & video, fashion & style, writing & performance), curated for work needing human aesthetic judgment.",
@@ -5281,7 +5241,7 @@ var browseTasteHumansSpec = {
5281
5241
  };
5282
5242
  var blockHumanSpec = {
5283
5243
  name: "block_human",
5284
- description: "Block a human profile from applying to your bounties or starting direct conversations with your account. Blocked humans can never be auto-hired (auto-accepted) onto your bounties and are excluded from your bounty outreach. Blocking a human removes them from your preferred humans list. Requires RENTAHUMAN_API_KEY.",
5244
+ description: "Block a human profile from applying to your bounties. Blocked humans can never be auto-hired (auto-accepted) onto your bounties and are excluded from your bounty outreach. Blocking a human removes them from your preferred humans list. Requires RENTAHUMAN_API_KEY.",
5285
5245
  input: BlockHumanRequest
5286
5246
  };
5287
5247
  var unblockHumanSpec = {
@@ -5841,7 +5801,7 @@ var DeleteIdentitySchema = Schema20.Struct({
5841
5801
  // src/tools/handlers/identity.ts
5842
5802
  var getAgentIdentity = {
5843
5803
  name: "get_agent_identity",
5844
- description: "Get your cryptographic agent identity. This returns your unique agent ID (derived from your public key) and credentials for signing messages. Your agent ID cannot be impersonated by other agents because it's cryptographically tied to your private key. Also shows which named identity is currently active. Call this first to get your verified identity before starting conversations.",
5804
+ description: "Get your cryptographic agent identity. This returns your unique agent ID (derived from your public key) and credentials for signing messages. Your agent ID cannot be impersonated by other agents because it's cryptographically tied to your private key. Also shows which named identity is currently active. Call this first before sending messages in supported conversations.",
5845
5805
  inputSchema: {
5846
5806
  type: "object",
5847
5807
  properties: {}
@@ -6100,8 +6060,8 @@ var checkAccountStatus = {
6100
6060
  capabilities: {
6101
6061
  search: true,
6102
6062
  bounties: true,
6103
- conversations: "requires direct-message eligibility",
6104
- messages: "requires an existing conversation or eligibility"
6063
+ conversations: "read existing and bounty-linked conversations",
6064
+ messages: "requires a supported task or support conversation"
6105
6065
  },
6106
6066
  message: messages.onboarding.accountStatusApiKeyConfigured
6107
6067
  });
@@ -7992,6 +7952,7 @@ var allTools = [
7992
7952
  ];
7993
7953
  function getVisibleTools(exposeIdentityTools, identityCount) {
7994
7954
  return allTools.filter((tool) => {
7955
+ if (tool.name === "start_conversation") return false;
7995
7956
  if (IDENTITY_TOOL_NAMES.has(tool.name) && !exposeIdentityTools && identityCount <= 1) {
7996
7957
  return false;
7997
7958
  }
@@ -75,6 +75,7 @@ declare const CreateBountyRequest: Schema.Struct<{
75
75
  autoAccept: Schema.optional<typeof Schema.Boolean>;
76
76
  autoAcceptMinMicScore: Schema.optional<Schema.filter<Schema.filter<typeof Schema.Number>>>;
77
77
  identityRequired: Schema.optional<typeof Schema.Boolean>;
78
+ excludedParticipantSourceBountyIds: Schema.optional<Schema.filter<Schema.Array$<typeof Schema.String>>>;
78
79
  micCheckRequired: Schema.optional<typeof Schema.Boolean>;
79
80
  aiManaged: Schema.optional<Schema.Literal<[true]>>;
80
81
  asOrg: Schema.optional<Schema.Literal<[true]>>;
@@ -146,6 +147,7 @@ declare const UpdateBountyRequest: Schema.Struct<{
146
147
  }>>;
147
148
  status: Schema.optional<Schema.Literal<["open", "in_review", "paused", "closed"]>>;
148
149
  identityRequired: Schema.optional<typeof Schema.Boolean>;
150
+ excludedParticipantSourceBountyIds: Schema.optional<Schema.filter<Schema.Array$<typeof Schema.String>>>;
149
151
  micCheckRequired: Schema.optional<typeof Schema.Boolean>;
150
152
  responseWindowHours: Schema.optional<Schema.filter<Schema.filter<typeof Schema.Number>>>;
151
153
  autoExpireGhosts: Schema.optional<typeof Schema.Boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rentahuman-mcp",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "description": "MCP server for AI agents to browse and book humans on rentahuman.ai",
5
5
  "keywords": [
6
6
  "ai",