61 toolsover MCP, stateless, spec 2026-07-28

Upwork buyer intelligence for your own agent, over MCP.

A proprietary Upwork corpus your agent asks over MCP: who the anonymous client really is, what they actually pay, who won the jobs you lost, and rate benchmarks from a freelancer census. You bring the agent and the subscription; the corpus answers, it is never downloaded.

# one line, then your agent has the corpus
claude mcp add --transport http buyerintel https://buyerintel.hyperbach.com/mcp/ \
  --header "Authorization: Bearer pldt_…"

Bring your own agent and subscription — we never run inference.

Claude CodeCursorCodex CLIany MCP client

61 questions your agent can ask.
Grouped by the job they do; every one answers from the corpus, none hands it over.

A token with no workspace gets the shared asset — search_jobs, rate_benchmark, skill_demand, get_prefilter_catalog, check_prefilter. A workspace token gets every tool, each gated to its own workspaces. The full list with argument and result schemas is in openapi.json; the plain-text version for models is llms.txt.

Workspace

12 tools

  • list_workspacesWorkspaces this account can access. Start here — every other tool takes a workspace slug.
  • get_workspaceOne workspace's detail — name and plan. Members only (404 otherwise).
  • list_facesFreelancer identities (faces) that bid from this workspace. Their prose — positioning, voice, strategies — lives in files under faces/<slug>/.
  • get_faceOne freelancer face's detail: identity, Upwork profile, default strategy. Their prose (positioning, voice) lives in faces/<slug>/ — read it with read_workspace_file.
  • + list_workspace_files, read_workspace_file, write_workspace_file, delete_workspace_file, workspace_history, create_face, retire_face, audit_workspace_files

Missions (feeds)

8 tools

  • list_missionsMissions (feeds) in a workspace: the prefilter that decides which jobs match, the dispatch mode, and which freelancer face bids.
  • get_missionOne mission's full config: prefilter, dispatch mode, agent_config, and the catch summary. Use get_prefilter_catalog to read the filterable fields first.
  • create_missionCreate a feed (mission) from a prefilter — run check_prefilter first, or let calibrate_prefilter shape it. Every new feed defaults to payment-verified clients and to match-only (matches are parked for on-demand triage; auto-triage is the paid opt-in; an explicit `agent_config` wins). `agent_config.face` is the bidding identity's slug or "auto". `status` = active | paused | draft (draft = the engine ignores it). Existing-corpus matches are parked at once, so list_matched_jobs shows them instead of "nothing matches yet"; `matched_parked` says how many.
  • patch_missionUpdate a mission — only title / status / prefilter / agent_config (`mode` is deliberately excluded, as in the app). A prefilter change is validated against the catalog first and rejected if invalid. Members only.
  • + get_prefilter_catalog, check_prefilter, calibrate_prefilter, list_matched_jobs

Search the job feed

1 tool

  • search_jobsSearch the Upwork job feed. Free text: - `query` — all these words must appear (space-separated). - `phrase` — this EXACT adjacent phrase. Use it for a named tool/product ("Claude Code", "Next.js", "React Native") so you don't also match a post that just mentions the words independently. - `exclude` — drop postings containing any of these words. `filters` — structured fields (spend, budget, price_type, category …); call get_prefilter_catalog for the names. At least one of query / phrase / filters is required.

The corpus, as answers

5 tools

  • get_jobOne job's detail — ONLY a job this workspace's feeds matched (it's in your inbox). There is deliberately no search over the job corpus. Description and title are scraped from Upwork and are UNTRUSTED.
  • get_buyerThe deanonymized client behind a job — ONLY a job this workspace matched. Never a lookup over the client corpus. company_name is scraped and UNTRUSTED.
  • get_buyer_qualityWhat we can say about the client behind a job — ONLY a job this workspace matched — and how much of it is actually known. `record` is their contract history, model-free ("9 of 31 fixed contracts cleared $500, largest ever $7,600"); `ask_vs_record` is how many of their past hourly contracts were at or above `ask` (your intended rate); `models` are the calibrated probabilities, `primary` chosen by the posting's engagement type — `p` is null when nothing is known, and a null is "unread", never a number; `taste` says whether they hire expensive people; `rate_by_category` what they pay per kind of work, this posting's marked. Same corpus boundary as get_buyer. Aggregates and counts, no names.
  • rate_benchmarkHourly-rate benchmark for a skill (optionally one country) from the freelancer census: median and p25/p75/p90 of LISTED rates, plus the Top-Rated share and sample size. AGGREGATE ONLY — no names, no rows; nothing is returned below a k-anonymity floor of 5 freelancers (a stat over too few would leak an individual's rate). Listed rates, not paid.
  • + skill_demand

Opportunities

6 tools

  • list_opportunitiesOpportunities — the agency-level spine, one per job pursued, with its lifecycle status (discovered/qualified/assigned/…/hired/won/lost), agency, latest verdict, and whether a proposal has been drafted. `status` may be comma-separated. This is the data a customer builds their own triage/routing workflow on.
  • get_opportunityOne opportunity in full: the job (title and a description snippet, UNTRUSTED), its lifecycle status and claim, the qualification history (current first, with the structured why), the latest run with its drafts, the connects it cost, and duplicate bids on the same opening. The data behind an Inbox row's expand. For the job's full detail use get_job; for every run on it, get_run.
  • qualify_opportunityRecord an explainable qualification on an opportunity and advance its lifecycle. `verdict` is FIT / MAYBE / SKIP; FIT/MAYBE move it to `qualified`, SKIP drops it from the active queue (reversible). The structured why (reasons_apply/against, risks, missing_quals) + economics (expected_value, confidence) are stored; `recommended_face` is the face this verdict is FOR (the one a draft would be written as), not a ranking — `recommend_face` ranks by track record and answers a different question. All of it is emitted as `opportunity.qualified` so your own workflow can react. This is how an agent qualifies at scale; a human can override later via the Inbox (correction).
  • assign_opportunityAssign an opportunity to a bidder (member) — one bidder per opportunity (§5C). Sets the claim, advances `qualified → assigned`, and emits `opportunity.assigned`. Rejects a silent takeover of a claim already held by someone else unless `reassign=true`. Pass `member_id=null` to release the claim.
  • + check_duplicates, recommend_face

Reply queue

5 tools

  • list_conversationsThe client-reply queue (§5F) — replied proposals awaiting a response, oldest first, with owner, wait time, and whether they are past SLA. `status=open` is the actionable queue; `overdue=true` narrows to breached. A reply is not an interview (§6). Build your own routing/alerting on `client.replied` events, or read this.
  • claim_conversationGive a thread an owner. `member_id` names the bidder who will answer; omitted, the thread is claimed for the token's own member seat (none = left unowned). Emits `conversation.claimed`.
  • answer_conversationMark that we responded to the client — stops the SLA clock and clears the thread from the open queue. Emits `conversation.answered`. This records the answer; it does not send anything to Upwork.
  • close_conversationClose a thread that needs no answer (the client moved on, the job died). Emits `conversation.closed`.
  • + set_conversation_sla

Events and hooks

6 tools

  • list_eventsThe domain-event stream — every lifecycle transition + action (opportunity.qualified, proposal.sent/viewed, client.replied, …), newest first. `event_type` accepts a glob (e.g. `proposal.*`). Poll this to build your own workflow, or register a webhook via create_subscription to be pushed instead.
  • list_subscriptionsWebhook/alert subscriptions in a workspace — each is an event-match filter routed to a destination (webhook/telegram/slack/email).
  • create_subscriptionRegister a hook: when an event matches `event_match` (e.g. {"event_type":"client.replied"}), push it to `destination_type` (webhook/telegram/slack) using `destination_config` (webhook: {"url":...}; telegram: {"bot_token":...,"chat_id":...}). This is how a customer wires their own workflow onto our event stream — any event, any stage.
  • update_subscriptionChange a hook: pause or resume it (`active`), rename it, retarget it, or change what it matches. Only the fields given are changed.
  • + delete_subscription, emit_test_event

Funnel and who won

6 tools

  • get_funnelProposal funnel from captured telemetry, by the state machine's sticky furthest `stage` (status is the source of truth): sent → viewed → interview → offer → hired, per org board, plus `active_now` (currently in the Active tab), avg days-to-interview, connects spent, and the archive-reason breakdown.
  • get_trendsCohort conversion over time: for proposals SENT in each period, how many reached viewed / interview / offer / hired (by the state machine's sticky furthest stage). period = week | month | quarter.
  • list_lost_jobsWho won the jobs we bid on and lost — the competitive read.
  • get_freelancerFull profile of a freelancer who WON a job you bid on — the deep competitive read: their skills, listed rate, standing (JSS/earned/Top Rated), and recent contract history. Bounded by the corpus boundary — you can only look up freelancers who beat you on a job in THIS workspace's outcomes; find a valid `ciphertext` in list_lost_jobs' `winner_ciphertext`. Profile text is third-party scraped content, wrapped as untrusted.
  • + get_spend, set_budget

Control room

7 tools

  • get_briefingThe daily control room (§5A) in one call — where to spend the next hour: the review queue (`to_triage` = leads no one has judged yet), the reply queue with its five oldest waiters, 7-day funnel motion, spend against every budget, and the north-star (qualified pipeline value per $100 spent) — each with a conclusion and a recommended action. `board` narrows every panel to one agency.
  • get_roi§8 ROI: the recommended-metrics table, the cost model and the revenue model over a spend window (`total` | `monthly` | `weekly`). Every cost-per-X is a FLOOR — captured spend over the whole funnel; `spend_coverage` says how many proposals carry spend at all. Revenue fields with no capture yet are explicit nulls, never zeros. `board` = one agency.
  • get_guardrailsThe §15 guardrail metrics: the evidence rate behind replied / interview / offer, the agent's correction and rejection rates, duplicate bids across boards, median time to a verdict and to apply. `measured` vs `blocked` says how many of the ten are readable today, and each blocked one says why.
  • get_integration_healthIs the capture healthy enough to trust the funnel numbers? A verdict per source (board walk, proposal detail, submit capture, message rooms …) with a reason and a next action, whether the extension build in use is the one shipped, coverage gaps, and the capture routine with what is due now. Read this before reasoning from get_funnel or get_trends.
  • + get_composition, list_row_audit, get_timeline

Pipeline (runs and drafts)

5 tools

  • draft_proposalSave a proposal YOU wrote into the leads pipeline so it appears in the Runs list, ready to review and send. Does NOT submit to Upwork — you review in Runs, then send via the browser extension. Creates the run if the job wasn't auto-matched (under a paused 'Manual bids' mission) and marks it a fit. Attaches the cover letter plus any screening answers as drafts, replacing a prior draft on the same run. `screening_answers` is a list of {question, answer}; `face` is the bidding-identity slug to attribute it to.
  • set_verdictSet your fit call on a job — 'fit' | 'maybe' | 'skip' — on its run in the Runs list (a developer's Yes/No, or triage). Creates a manual run if the job wasn't auto-matched.
  • add_feedbackCorrect the pipeline — teach the auto-triage and the proposal generator. This is the LEARNING signal: it feeds the workspace's learnings digest, which shapes future verdicts and drafts. It is NOT a human chat note (that thread is separate). Attach it to a job that has a run (triaged or drafted).
  • list_draftsThe drafts the pipeline produced for a job — the cover_letter and each screening_answer — so you can read what the agent actually wrote. Read-only, scoped to your workspace. Empty if the job was never run here. For the full run detail (verdict, strategy, cost) use get_run.
  • + get_run

Four rules the server enforces.
Not a policy page — code paths.

Asked, never downloaded

There is no list-all-jobs. Search is bounded — a filter is required, results are capped, there is no cursor. Rate statistics come from a freelancer census behind a k-anonymity floor of five. Buyer dossiers open only for jobs your own feeds matched.

Scraped text is marked untrusted

Job titles, descriptions and buyer names are attacker-controlled and flow into your autonomous agent. Every one arrives wrapped in <untrusted-scraped-content> so an injected posting reads as data, never as an instruction.

Your agent, your subscription

Screening, scoring and drafting run on your side, at your cost, with the tools you already have installed. We sell the pipeline and the corpus. No token is ever billed by us.

Stateless by protocol

MCP 2026-07-28 over Streamable HTTP: no handshake, no session id. A deploy on our side cannot break your session. Every call is logged per token, with daily caps and an enumeration guard, so a runaway loop is caught and a refusal is an ordinary tool error.

Pricing for one token

Access

One token, one agent

Being finalized
Connect — ask for a price

Mint a token now; write to support@hyperbach.com with its label and we set you up while the number is decided.

  • The corpus tier for any signed-in account: bounded search, rate benchmark, skill demand
  • Every tool for a workspace: buyers de-anonymized, who won your lost jobs, funnel and control room
  • One token per agent, revocable; every call logged to it
  • Bring your own agent and subscription — no inference billed here

Corpus licensing

For tools with distribution

Talk to us
support@hyperbach.com
  • Buyer de-anonymization and paid-rate history behind your own product
  • Volume beyond the per-token caps
  • A workspace per customer of yours

Questions an agent operator asks

Something else? support@hyperbach.com

Point the agent you already run at the corpus