hyreflow docshyreflow docsDocumentation

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 its recipes field.

  • 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 a side_effect flag 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 takes rows (up to 100 row objects) instead of payload to 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. rows is exclusive with payload and method. A step that is still running when the poll budget ends reports still_enriching with job_id and a resume object (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 with hyreflow_dataset_read or hand the whole file over with hyreflow_dataset_export; a still_enriching row 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 identical rows — 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. Use personal_email instead 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) use linkedin_profile instead.

    {"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 its ds_ id as input (a search's results, say) so the rows are not re-sent. Its steps execute per row; use hyreflow_tools_execute with an enrichment waterfall plus rows when you want provider-level batching. The call waits about 20 seconds: a larger run comes back with _meta.status: "running" and a run_id, and calling hyreflow_enrich_run again with just that run_id (free) returns its state until it reads completed. While it runs, _meta.progress counts rows done of the rows in range; once complete, the poll carries the same summary (per-provider hit counts) and credits_charged that 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 back still_enriching with its job_id. Fetch that row later with hyreflow_enrich_job {provider, job_id}, which returns the same settled shape as GET /enrich/jobs/{provider}/{job_id} (status pending/settled/failed/expired, plus charged, email, result once 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. Pass candidates (for example the rows a CRM or ATS search returned) or input (a ds_ 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 a run_id to poll by calling hyreflow_shortlist again 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: true quotes 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's photo_url, or a raw AI Ark row's profile.picture.source; AI Ark or LinkedIn) into a hyreflow artifact page, which can't load images from other sites. Pass a dataset_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 under skipped. 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. 0 does not rule out pending rows on another dataset page. It is null when 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: true once 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 its SKILL.md, or add a path like provider-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. Pass version to read another one, such as your own draft still waiting for approval.
  • hyreflow_custom_skill_save: create a skill (scope personal or org) or, with skill_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"