Skip to main content
All 41 tools registered by the OpenTrain MCP server, grouped by surface. Each tool’s scope, feature flag, and claim requirements mirror the endpoint it wraps — the linked endpoint page has the full request/response shapes and error tables. Every tool returns a human-readable text summary plus the exact API response in structuredContent; failures return isError: true with the HTTP status and the error envelope. Scopes and feature flags are explained in Scopes and Capabilities.
GroupTools
Auth and identityregister_agent, claim_account, claim_status, auth_status, capabilities
Jobscreate_job_draft, update_job_draft_fields, publish_job, update_published_job, close_job, list_jobs, search_jobs
Proposals and candidateslist_proposals, get_proposal, get_freelancer_profile, invite_freelancer, hire_proposal
Messagesread_messages, send_message, start_proposal_conversation
Contracts and milestoneslist_contracts, get_contract, create_milestone, request_milestone_funding, request_milestone_approval, get_approval, end_contract
Creditsget_credits, list_credit_ledger, create_credit_top_up, get_credit_top_up
Updatespoll_updates
Webhookscreate_webhook, list_webhooks, get_webhook, delete_webhook
Tokenslist_tokens, revoke_token
Teamget_team, invite_team_member
Paymentslist_pending_payments
All tool names below carry the opentrain_ prefix.

Auth and Identity

opentrain_register_agent

Register a brand-new anonymous OpenTrain agent account — no prior credentials needed. The new ot_pat_ token and claim token are saved to the shared config file, so every other tool works immediately afterwards. Refuses to overwrite existing saved credentials unless force is set. Next step: ask the human for their email and call opentrain_claim_account.
ParameterTypeDescription
agentNamestring, optionalDisplay name for the agent identity (e.g. “Claude Code”)
organizationNamestring, optionalName for the employer organization created with the account
forceboolean, optionalOverwrite existing saved credentials with a brand-new account
Requires: nothing — anonymous and tokenless. Wraps: POST /api/agent/identity

opentrain_claim_account

Send the human owner a claim invite for the agent-registered account — the start of the claim ceremony. OpenTrain emails them a verification link; once they accept, they own the account and can add billing. Follow up with opentrain_claim_status.
ParameterTypeDescription
emailstring, requiredThe human owner’s email address
claimTokenstring, optionalClaim token from registration; defaults to the saved one
Requires: a valid, unexpired claim token (~24h window from registration). Wraps: POST /api/agent/identity/claim

opentrain_claim_status

Check whether the human has completed the claim. When the claim completes, the stored API token is upgraded to the claimed account automatically. A slow_down status means you are polling too fast — respect the poll interval from opentrain_claim_account.
ParameterTypeDescription
claimTokenstring, optionalClaim token to check; defaults to the saved one
Requires: a valid claim token with an active claim attempt. Wraps: POST /api/agent/oauth/token

opentrain_auth_status

Confirm that the configured token can authenticate, and see the account’s user id, account type, claim state, and granted scopes. No parameters. Requires: any valid token. Wraps: GET /auth/me

opentrain_capabilities

Discover which job-drafting features are enabled for the account plus the full job field/enum catalog — use it to probe feature availability before drafting. No parameters. Requires: any valid token; the public_api_job_drafting feature must be enabled for the account. Wraps: GET /job-drafts/capabilities

Jobs

opentrain_create_job_draft

Create an unpublished job draft from a full job description or supported import payload — the primary drafting workflow. OpenTrain parses the description into structured job fields server-side; the response’s validation state lists each missing field with an ask: question to relay to the human, its type, allowed enum values, and the set: field names for opentrain_update_job_draft_fields.
ParameterTypeDescription
jobDescriptionstring, optionalFull plain-text job description or project brief (primary workflow)
titlestring, optionalTitle to prepend for plain-text imports
externalIdstring, optionalSource-system id for audit/idempotency
idempotencyKeystring, optionalReuse the same key to avoid duplicate drafts on retry
canonicalJobobject, optionalOpenTrain canonical job object (format=opentrain_canonical)
importPayloadobject, optionalSupported import payload, e.g. schema.org JSON-LD
Requires: jobs:write + the public_api_job_drafting feature. Wraps: POST /job-drafts

opentrain_update_job_draft_fields

Fill in or correct fields on an existing unpublished draft. Ask the human each missing field’s ask: question, then patch the answers using the set: field names — never ask the human to author raw JSON. This tool never publishes; use opentrain_publish_job.
ParameterTypeDescription
jobIdstring, requiredExisting unpublished draft job id
patchobject, requiredField patch keyed by OpenTrain field names, e.g. {"experienceLevel": "INTERMEDIATE", "pricePerHour": 12}
Requires: jobs:write + the public_api_job_drafting feature. Wraps: PATCH /job-drafts/{jobId}

opentrain_publish_job

Publish a draft live on the marketplace. Runs the same validation and moderation pipeline as the in-app publish flow and is subject to per-account daily publish limits. Returns the live job URL.
ParameterTypeDescription
jobIdstring, requiredUnpublished draft job id to publish
Requires: jobs:write + the public_api_job_publishing feature. Wraps: POST /jobs/{id}/publish

opentrain_update_published_job

Update fields on a live published (OPEN) job. The revised listing is re-checked by moderation inline; if blocked, the job is automatically unpublished back to draft and the response explains what to fix. For unpublished drafts use opentrain_update_job_draft_fields instead.
ParameterTypeDescription
jobIdstring, requiredPublished (OPEN) job id
patchobject, requiredField patch, same shape as opentrain_update_job_draft_fields
Requires: jobs:write + the public_api_job_publishing feature. Wraps: PATCH /jobs/{id}

opentrain_close_job

Close (archive) a published job so it stops accepting proposals and leaves public listings. Existing contracts are unaffected. Idempotent — closing an already-archived job reports alreadyClosed.
ParameterTypeDescription
jobIdstring, requiredPublished job id to close
Requires: jobs:write + the public_api_job_publishing feature. Wraps: POST /jobs/{id}/close

opentrain_list_jobs

List the account’s own jobs (all statuses, newest first) with pagination.
ParameterTypeDescription
statusstring, optionalFilter: DRAFT, OPEN, ONGOING, COMPLETED, ARCHIVED, or PENDING_APPROVAL
cursorstring, optionalPagination cursor
limitnumber, optionalMax jobs to return, 1–100 (default 25)
Requires: jobs:read. Wraps: GET /jobs/mine

opentrain_search_jobs

Search the public OpenTrain job marketplace — useful for calibrating rates and seeing how similar work is scoped before posting.
ParameterTypeDescription
qstring, optionalFree-text search query
categorystring, optionalCategory filter
languagestring, optionalLanguage filter
countrystring, optionalISO country code
payTypestring, optionalPayment type filter
limitnumber, optionalMax results, 1–50
cursorstring, optionalPagination cursor
Requires: nothing — tokenless public read (120 requests/minute per IP). Wraps: GET /jobs

Proposals and Candidates

opentrain_list_proposals

List proposals/candidates for a job with statuses, bids, AI interview scores, and resume match scores — the primary tool for reviewing and ranking who to hire. Use opentrain_get_proposal for one candidate in depth.
ParameterTypeDescription
jobIdstring, requiredJob id to list proposals for
statusstring, optionalFilter such as UNREVIEWED, SHORTLISTED, HIRED, or DECLINED
cursorstring, optionalPagination cursor
limitnumber, optionalMax proposals, 1–100 (default 25)
Requires: proposals:read; the job must be yours. Wraps: GET /jobs/{id}/proposals

opentrain_get_proposal

Read a full proposal/candidate evaluation: status, bid, masked candidate, AI-interview score and summary, location/identity verification, labeling assessment, and contract state.
ParameterTypeDescription
proposalIdstring, requiredProposal id to read
includeInterviewboolean, optionalAlso fetch the sanitized AI-interview transcript
Requires: proposals:read; the proposal must be on a job you own. Wraps: GET /proposals/{proposalId} (+ GET /proposals/{proposalId}/interview when includeInterview is true)

opentrain_get_freelancer_profile

Read a masked AI trainer profile for candidate evaluation: title, bio, skills, stats (earned, billed hours, job success), work and labeling experience, education, reviews, and languages. Names are masked to first name + last initial pre-hire, and personal contact details are never returned — see Privacy and Work Email.
ParameterTypeDescription
idOrSlugstring, requiredAI trainer user id or public profile slug
Requires: proposals:read. Wraps: GET /freelancers/{idOrSlug}

opentrain_invite_freelancer

Invite an AI trainer to a published job, creating a proposal they can respond to. Idempotent: re-inviting the same person returns the existing proposal with alreadyInvited: true.
ParameterTypeDescription
jobIdstring, requiredPublished job id
freelancerIdstring, requiredAI trainer user id to invite
Requires: proposals:write + the public_api_hiring feature + a claimed account. Wraps: POST /jobs/{id}/invites

opentrain_hire_proposal

Request a hire from a proposal. Never hires anyone or moves money — records a pending approval (type: "proposal_hire") and returns 202 with an approvalUrl a signed-in human must confirm in the OpenTrain app. On confirm, OpenTrain creates the contract and funds the first escrow milestone (the human picks card or credits). A 409 with details.reason: "payment_method_required" includes a billingUrl; not_fit_confirmation_required means retry with confirmNotFitOverride: true if intentional; already_accepted means the proposal was already hired. Re-requesting with the same terms returns the same pending approval.
ParameterTypeDescription
proposalIdstring, requiredProposal id to hire from
milestoneobject, requiredFirst escrow milestone: {name?, description?, amount (USD, required), dueDate?}
confirmNotFitOverrideboolean, optionalConfirm hiring a proposal previously marked “Not a fit”
Requires: proposals:write + the public_api_hiring feature + a claimed account + a payment method or covering credit balance. Wraps: POST /proposals/{proposalId}/hire

Messages

opentrain_read_messages

Read authorized conversation summaries or messages. Omit conversationId to list summaries; provide it to read messages. Never creates conversations or sends messages.
ParameterTypeDescription
conversationIdstring, optionalConversation to read; omit to list summaries
cursorstring, optionalPagination cursor
limitnumber, optionalMax records, 1–100
directionolder | newer, optionalMessage pagination direction (with conversationId)
filterall | job | proposal, optionalSummary filter (without conversationId)
unreadOnlyboolean, optionalOnly conversations with unread messages (without conversationId)
Requires: messages:read; you only see conversations you participate in. Wraps: GET /messages

opentrain_send_message

Send a plain-text message into an existing conversation the token owner participates in. Runs the same membership, rate-limit, and content-policy checks as the in-app messaging flow. This tool never creates conversations — they come from proposals, invites, and hires.
ParameterTypeDescription
conversationIdstring, requiredExisting conversation id
contentstring, requiredPlain-text message (max 10,000 chars)
Requires: messages:write + the public_api_messaging_writes feature + a claimed account. Wraps: POST /messages

opentrain_start_proposal_conversation

Start (or fetch) the pre-hire direct-message thread for a proposal so you can message the candidate before hiring. Idempotent get-or-create; returns the conversationId to use with opentrain_send_message. Employer side only.
ParameterTypeDescription
proposalIdstring, requiredProposal to open the pre-hire thread for
Requires: messages:write + the public_api_messaging_writes feature + a claimed account. Wraps: POST /proposals/{proposalId}/conversation

Contracts and Milestones

opentrain_list_contracts

List contracts (hired AI trainers), each with milestones, the post-hire job DM conversationId, and the masked freelancer identity (first name + last initial).
ParameterTypeDescription
jobIdstring, optionalFilter to one job
statusactive | ended, optionalStatus filter; omit for both
Requires: payments:read. Wraps: GET /contracts

opentrain_get_contract

Read one contract in detail: status, milestones with funding/approval state, AI trainer identity, the post-hire job DM conversationId, and the budget snapshot (funded vs consumed, state OK/LOW/DEPLETED).
ParameterTypeDescription
contractIdstring, requiredContract id to read
Requires: payments:read. Wraps: GET /contracts/{contractId}

opentrain_create_milestone

Create a new unfunded milestone on an existing contract. No money moves at creation — use opentrain_request_milestone_funding afterwards.
ParameterTypeDescription
contractIdstring, requiredContract to add the milestone to
descriptionstring, requiredDescription of the work to be delivered
namestring, optionalShort milestone name
amountUsdnumber, optionalMilestone amount in USD
volumenumber, optionalUnit volume (e.g. label count) for per-unit milestones
dueDatestring, optionalDue date (ISO 8601)
Requires: payments:write + the public_api_payments_write feature + a claimed account. Wraps: POST /contracts/{contractId}/milestones

opentrain_request_milestone_funding

Request escrow funding for a milestone. This does not move money: it returns a pending approval with an approvalUrl that a signed-in human must open and confirm (expires in ~72h) — the co-sign pattern. Watch opentrain_poll_updates for approval.confirmed, or re-check with opentrain_get_approval.
ParameterTypeDescription
milestoneIdstring, requiredMilestone to fund
Requires: payments:write + the public_api_payments_write feature + a claimed account + a payment method on file. Wraps: POST /milestones/{milestoneId}/fund

opentrain_request_milestone_approval

Request approval (payment release) of a funded milestone. Like funding, this only creates a pending human approval with an approvalUrl (~72h expiry) — no money moves until the human confirms.
ParameterTypeDescription
milestoneIdstring, requiredFunded (ACTIVE_FUNDED) milestone to release
Requires: payments:write + the public_api_payments_write feature + a claimed account. Wraps: POST /milestones/{milestoneId}/approve

opentrain_get_approval

Check the status of a pending human co-sign approval (milestone funding, release, or contract end): pending, confirmed, declined, or expired, plus the execution result once confirmed.
ParameterTypeDescription
approvalIdstring, requiredApproval id from a fund/approve/end request
Requires: payments:read. Wraps: GET /approvals/{approvalId}

opentrain_end_contract

End a contract. With no funded milestones it ends immediately; if funded escrow is at stake, the call instead returns a pending approval with an approvalUrl a human must confirm — no funds move until then.
ParameterTypeDescription
contractIdstring, requiredContract to end
Requires: payments:write + the public_api_payments_write feature + a claimed account. Wraps: POST /contracts/{contractId}/end

Credits

opentrain_get_credits

Read the prepaid credit balance: available, reserved (escrow holds), and total. No parameters. Requires: payments:read + the public_api_credits feature. Wraps: GET /credits

opentrain_list_credit_ledger

Page through the credit ledger — top-ups, escrow holds, hold releases, captures, refunds, and adjustments, newest first. Each entry links the related top-up, proposal, contract, or milestone ids.
ParameterTypeDescription
cursorstring, optionalnextCursor from a previous page
limitnumber, optionalPage size, 1–100 (default 50)
Requires: payments:read + the public_api_credits feature. Wraps: GET /credits/ledger

opentrain_create_credit_top_up

Start a credit top-up. No money moves from this call: it returns a Stripe Checkout checkoutUrl that a signed-in human must open and pay (expires in ~24h). Once paid, the balance updates automatically.
ParameterTypeDescription
amountUsdnumber, requiredTop-up amount in USD (min $10, max $10,000)
Requires: payments:write + the public_api_credits feature + a claimed account. Wraps: POST /credits/top-ups

opentrain_get_credit_top_up

Check a top-up’s status: pending (awaiting human payment), completed (credits added), canceled, or expired.
ParameterTypeDescription
topUpIdstring, requiredTop-up id from opentrain_create_credit_top_up
Requires: payments:read + the public_api_credits feature. Wraps: GET /credits/top-ups/{topUpId}

Updates

opentrain_poll_updates

Poll the delta feed of account events (new proposals, proposal status changes, new messages, contracts, milestone changes, pending payments, confirmed approvals, budget state changes) in one cheap call instead of re-reading every resource. Payloads carry IDs only — fetch details with the matching read tool. Event visibility follows the token’s scopes.
ParameterTypeDescription
cursorstring, optionalnextCursor from the previous poll; omit on the first poll
limitnumber, optionalMax events, 1–200 (default 50)
Requires: at least one of proposals:read, messages:read, payments:read. Wraps: GET /updates

Webhooks

opentrain_create_webhook

Subscribe an HTTPS URL to platform events (push instead of polling). Deliveries are signed with HMAC-SHA256 — see Verify Webhook Signatures. The signing secret is returned once in this response; store it immediately. The subscription only receives events created after it.
ParameterTypeDescription
urlstring, requiredHTTPS endpoint that will receive signed deliveries
eventTypesstring[], requiredEvent types to subscribe to, e.g. ["proposal.received", "message.received"]
Requires: webhooks:manage + the public_api_webhooks feature + the matching read scope for each subscribed event type. Wraps: POST /webhooks

opentrain_list_webhooks

List all webhook subscriptions with URL, event types, and status. Signing secrets are never included. No parameters. Requires: webhooks:manage + the public_api_webhooks feature. Wraps: GET /webhooks

opentrain_get_webhook

Read one webhook subscription: URL, event types, status (ACTIVE or DISABLED), and failure/disable details. The signing secret is never returned — if lost, delete and re-create the subscription.
ParameterTypeDescription
webhookIdstring, requiredWebhook subscription id
Requires: webhooks:manage + the public_api_webhooks feature. Wraps: GET /webhooks/{webhookId}

opentrain_delete_webhook

Delete a webhook subscription and stop its deliveries. This is also how a DISABLED subscription is resumed: delete it and create a new one (which mints a new secret).
ParameterTypeDescription
webhookIdstring, requiredWebhook subscription id to delete
Requires: webhooks:manage + the public_api_webhooks feature. Wraps: DELETE /webhooks/{webhookId}

Tokens

opentrain_list_tokens

List the account’s API tokens with masked previews, scopes, status, and last-used timestamps — secrets are never shown. No parameters. Requires: any valid token — token management needs no specific scope or feature flag. Wraps: GET /tokens

opentrain_revoke_token

Revoke an API token by id. Irreversible — the token stops working immediately.
Revoking the token the MCP server itself is using breaks every subsequent call. Mint a replacement over HTTP with POST /tokens and switch to it first.
ParameterTypeDescription
tokenIdstring, requiredId of the token to revoke
Requires: any valid token — token management needs no specific scope or feature flag. Wraps: DELETE /tokens/{tokenId}

Team

opentrain_get_team

Read the employer team: organization, members with roles, and pending email invites. No parameters. Requires: team:read + the public_api_team feature. Wraps: GET /team

opentrain_invite_team_member

Invite a human to the employer team by email, giving them shared access to jobs and the team inbox once they accept. Inviting an existing member returns already_member; users with existing accounts are added directly (member_added).
ParameterTypeDescription
emailstring, requiredEmail of the human to invite
Requires: team:write + the public_api_team feature + a claimed account. Wraps: POST /team/invites

Payments

opentrain_list_pending_payments

List pending payments on the account — read-only; never releases funds. No parameters. Requires: payments:read. Wraps: GET /payments/pending