MCP Reference
The tools, playbooks, billing and recording behavior behind an MCP connection.
What a connected agent sees, once setup is done. The server speaks the 2024-11-05, 2025-03-26, 2025-06-18 and 2025-11-25 revisions of the protocol.
Tools
-
hyreflow_tools_search: find tools by intent ("find software engineers", "verify emails"). The usual entry point. Names a matching recipe in itsrecipesfield. -
hyreflow_tools_describe: input contract and exact credit cost before running. Argument-priced and surcharged methods quote a worst case (credits_max, surcharge included), not a base price. Also reports aside_effectflag per method, so an agent can tell a reversible lookup from a write to your ATS. -
hyreflow_tools_execute: run it. Waterfall sourcing like people search runs exactly as the CLI does it: house provider order, dedup, BYOK skips. An enrichment waterfall (email_enrichment,personal_email,linkedin_profile,phone_enrichment) also takesrows(up to 100 row objects) instead ofpayloadto enrich many people in one call: the chain runs stage by stage and a provider that accepts a batch (FullEnrich) gets one job for every pending row, billed per row.rowsis exclusive withpayloadandmethod. A step that is still running when the poll budget ends reportsstill_enrichingwithjob_idand aresumeobject (tool,method,id_arg), and ends that row's chain there — no further provider runs for it. The job settles on its own server-side and bills once when it finishes; resume it sooner with a poll (free while the job runs; a finished job bills only the rows it revealed, once) rather than resending the row, which would start and bill a second job. A multi-row call also lands its rows in a dataset (_meta.dataset_id) — read them withhyreflow_dataset_reador hand the whole file over withhyreflow_dataset_export; astill_enrichingrow fills in there on its own once its job settles, with no re-poll needed just to complete the dataset. If the whole call comes back with nothing at all (a connector timeout, a dropped connection), resend the identicalrows— within ~15 minutes it replays the first call's dataset for free (_meta.replayed,charged: 0) instead of billing a second run:{"tool":"email_enrichment","rows":[{"first_name":"Jane","last_name":"Doe","company_domain":"acme.example.com"}]}Pass those arguments to
hyreflow_tools_execute. Usepersonal_emailinstead for candidates, but only when the user explicitly asked for personal emails. A bare "enrich" is ambiguous: ask which channel, or for screening/context (not contact details) uselinkedin_profileinstead.{"tool": "<resume.tool>", "method": "<resume.method>", "payload": {"<resume.id_arg>": "<job_id>"}} -
hyreflow_workflows_list/hyreflow_workflow_run/hyreflow_workflow_runs: list this workspace's saved workflows, run one by the name or id that list returns, poll the run id it gives back. To drive it from a prompt:Run my "<workflow name>" workflow through hyreflow and tell me when it finishes, with the total credits spent. -
hyreflow_enrich_run: generic ordered, per-column enrichment over rows, or over a whole dataset by passing itsds_id asinput(a search's results, say) so the rows are not re-sent. Its steps execute per row; usehyreflow_tools_executewith an enrichment waterfall plusrowswhen you want provider-level batching. The call waits about 20 seconds: a larger run comes back with_meta.status: "running"and arun_id, and callinghyreflow_enrich_runagain with just thatrun_id(free) returns its state until it readscompleted. While it runs,_meta.progresscounts rows done of the rows inrange; once complete, the poll carries the samesummary(per-provider hit counts) andcredits_chargedthat a run finishing inside the wait returns — except a run the service resumed after a restart, which carries its rows but no summary. Re-sending an identical run within 15 minutes returns the first one at no charge. It polls each async step against a short in-request budget; a step still running when that budget ends comes backstill_enrichingwith itsjob_id. Fetch that row later withhyreflow_enrich_job {provider, job_id}, which returns the same settled shape asGET /enrich/jobs/{provider}/{job_id}(statuspending/settled/failed/expired, pluscharged,email,resultonce settled) — free while pending, billed once on the poll that finds it settled. -
hyreflow_shortlist: bulk-screen candidates against a job description, ranked with a tier and per-category scores. Passcandidates(for example the rows a CRM or ATS search returned) orinput(ads_dataset id). The question set is generated once per job description and reused. The call waits about 20 seconds: a finished screen returns the top 25, with every ranked row in_meta.dataset_id; an unfinished one (always the first screen of a new job description) returns arun_idto poll by callinghyreflow_shortlistagain with just that id. Polling is free, and re-sending an identical screen within 15 minutes returns the first one at no charge.dry_run: truequotes the cost first. -
hyreflow_billing_balance: check spend. -
hyreflow_onet_lookup: job title → O*NET-SOC codes. Free, and needed before job-openings discovery, which takes codes rather than titles. "Head of Talent Acquisition" resolves by dropping the seniority prefix; each result carries the official title and description so a loose match can be checked. -
hyreflow_extract_image: puts candidate profile photos (a row'sphoto_url, or a raw AI Ark row'sprofile.picture.source; AI Ark or LinkedIn) into a hyreflow artifact page, which can't load images from other sites. Pass adataset_id(up to 500 photos, read by the engine) or up to 100 links. Returns a link that's good for 15 minutes: post the finished page to it and it comes back with the photos inside. Expired or unreachable links come back underskipped. Free. -
hyreflow_feedback: send feedback or a bug report, returns the filed issue's URL. Free. The session is attached so we can see the run that prompted it. Your client will ask before sending: it reaches real people.
Every result reports the credits it charged in _meta.
Rows still being fetched
A still_enriching row is not a miss: its email is still being fetched and usually arrives within
one to two minutes, so it does not yet mean "no email found". hyreflow_tools_execute,
hyreflow_enrich_run and hyreflow_dataset_read results say so in _meta:
pending: how many rows in this response are still being fetched.0does not rule out pending rows on another dataset page. It isnullwhen the call can't know whether they have landed since (for example a later poll of a finished run), so read the dataset instead.pending_jobs: the open jobs, when the call has them.poll_after_s: how long to wait before checking again (20 seconds).instruction: the exact steps to follow, written for the assistant.final:trueonce nothing is pending and every row has been seen, which means a fresh call's rows, a read of the whole dataset, or a finished run that left nothing pending. One page of a longer dataset, or a run still going, never carries it.
Check again every poll_after_s seconds with hyreflow_dataset_read on _meta.dataset_id, with
hyreflow_enrich_job for each job, or, for a run still going, with hyreflow_enrich_run and only its
run_id. All three are free. For a dataset that fits in one read, report the final count only when
_meta.final is true. For a larger dataset, follow next_offset until has_more is false and check
every page; a page with pending: 0 is not a stop signal. Once the run has completed, recheck pages with
pending or unstamped rows until all rows have a final status. If the assistant stops early, it should say
how many rows are still pending. Resending a row starts and bills a second job.
Spend confirmation
The server enforces a pre-spend check on hyreflow_tools_execute, hyreflow_enrich_run and
hyreflow_shortlist. When a
call's estimate exceeds the confirmation threshold — 50 credits, or a quarter of what the
workspace has left, whichever is lower — nothing runs and nothing is charged. The lower bound is the
one that matters on a small balance: a 30-credit batch is rounding error on a full account and more
than half of a nearly-empty one, and it is the second case that needs asking. threshold_basis says
which bound applied. For an enrichment the estimate is the typical cost — each provider in a
waterfall weighted by how often it actually hits — with the worst case beside it as
total_max_credits; a chain with too little history to say is gated on its worst case. The result
is a structured confirmation_required object, also mirrored in
_meta, with the estimate, the current balance and a short-lived token:
{
"confirmation_required": true,
"cost_estimate": {"credits": 38.0, "estimated_usd": 3.8, "tool": "personal_email", "rows": 10},
"current_balance": 120.0,
"balance_after": 82.0,
"confirm_token": "cfm_...",
"expires_in_s": 600
}The agent shows the user the cost and asks for approval, then repeats the identical call with
confirm_token set to that token. The token is bound to the workspace, the exact arguments and the
quoted price, and expires after ten minutes: a changed payload, a different price or an expired token
returns a fresh confirmation_required instead of running. Calls at or under the threshold, dry_run
calls and calls served by your own provider key (BYOK) flow through without the extra round trip.
A search quotes what its coverage mode can actually spend: coverage: max visits every source to
exhaustion and is quoted for that, while the default single is quoted for the pages the ask actually
needs — ceil(limit / page_size) — since a limit above one vendor page forces paging to fill the
quota. The quote then becomes that search's spend cap for the rest of the call, whether or not it
triggered a confirmation_required — if paging further would cost more than the quote, it returns the
rows it has and marks the step estimate_cap rather than billing past it.
Two things the check does not hold: a saved workflow started with hyreflow_workflow_run, and a job
whose price is only known once the provider answers (an async scrape that bills per delivered record).
Neither is held by a spend cap unless you set one yourself on the billing page, so watch
_meta.credits_charged on those paths. A confirm_token itself is single-use — resending the identical
call with the same token a second time gets a fresh confirmation_required instead of a second charge.
Every paid result also carries _meta.budget_warning when the run left the balance under 50 credits or
consumed half or more of what was available, so the client sees a low-balance signal inline rather than
after the next call fails.
Tools that only read are marked read-only, so a client that groups tools by permission can
auto-approve the safe set: catalog search, playbook reading, run status, balance. Anything that
spends credits or writes to a connected system stays outside that group and keeps asking:
hyreflow_tools_execute, hyreflow_enrich_run, hyreflow_shortlist, and any workflow run.
The playbooks come with it
An MCP client installs nothing, so the agent skills are served over the connection instead, in full: the recruiting playbook, a playbook per provider covering access rules, payload shapes and cost traps, the pipeline recipes, and the sub-agent prompts.
Reading a provider's playbook before executing that provider's tool is the difference between a
call that works and one that burns credits on a malformed payload. Three things point at the right
one: hyreflow_tools_search names a recipe, hyreflow_tools_describe names a provider playbook,
and every hyreflow_tools_execute result carries the same pointer in _meta.playbook.
Connecting also hands the agent the routing table: the index mapping a task ("a job description → a shortlist", "a company just raised") to the document that covers it, so it knows which playbook to open before reading anything.
They arrive two ways, and every client supports at least one:
- as MCP resources, addressed
hyreflow://skills/<skill>/<path>: clients that show resources let you attach one to a conversation directly. - as tools:
hyreflow_skills_list(every skill and document),hyreflow_skill_read(one document in full: a skill name alone returns itsSKILL.md, or add a path likeprovider-playbooks/apollo.md),hyreflow_skill_search(find a document by term; searching a provider name is the fastest route to its playbook).
Your own skills
Skills your workspace writes itself (Custom skills) come over the same connection. The agent is told to check them at the start of a task and follow any that fit:
hyreflow_custom_skills_list: your personal skills and the team's skills, with a name and description each.hyreflow_custom_skill_read: one skill's files at its live version, plus its version history. Passversionto read another one, such as your own draft still waiting for approval.hyreflow_custom_skill_save: create a skill (scopepersonalororg) or, withskill_id, save a new version. Ask your agent to "save this as a skill" and it uses this. A team version waits for the workspace owner, who approves it on the dashboard's Skills page. There is no approve tool.
The two read tools are marked read-only, so a client can run them without asking. A save isn't, so a client asks before running it.
Billing
Tool calls bill identically on every surface: MCP, CLI, or API. A connected client counts as one
session until it goes 24 hours without a charge. Its next call then starts a new session, so a
per-session spend cap covers each stretch of work, and every charge lands on the approved
workspace's balance. A connection inherits your workspace's default per-session cap if you have set
one on the billing page; there is no cap otherwise, because a limit you did not choose is one you
cannot raise from inside the client. With a cap set, paid calls stop with session spend limit reached
once it is used up, until a reconnect or 24 idle hours start a fresh session. See pricing.
Run recording
A run trace records Hyreflow tool inputs and outputs, provider, timing, outcome, and client information
when available, grouped per connection within your workspace. The tools that spend credits require a
user_prompt: the request that drove the call, which your agent sends so a trace reads as your ask
followed by the tools it drove. Your surrounding conversation is not captured. Traces carry workspace and user
identifiers and account email for support attribution. Recognized contact fields and recognizable email
addresses, profile links, and phone numbers are filtered from trace payloads; free-form text is not fully
anonymized. Recording never changes results or billing.
Recording is on by default. A workspace can also be set to always record or never record, and where it is set it takes precedence over anything a client sends. Ask us what your workspace is set to, or to change it.
A client that lets you set request headers can send X-hyreflow-Telemetry: 0, honored unless your
workspace is pinned. In Claude Code, add it when you connect:
claude mcp add --transport http hyreflow https://recruit.hyreflow.ai/api/v2/mcp \
--header "X-hyreflow-Telemetry: 0"