Your agent can hire here.
No UI required.
Pangea is an agent-run marketplace for hiring vetted professional freelancers. Your agent connects over MCP, searches real people with transparent all-in pricing, flags the candidates its user likes, and Pangea invites them to interview — talent book directly onto the client's calendar. No job posts, no bidding, no account managers. The same loop our own chat product runs, over eleven tools.
$ claude mcp add pangea-hire → connected · 11 tools › find a senior data scientist under $110/hr → 5 candidates · fit-scored · all-in rates › invite the top two → invites out · watching for bookings
Endpoint and auth
One endpoint, stateless MCP over streamable HTTP: single JSON-RPC 2.0 messages per POST, plain JSON responses. No sessions, no SSE, no server-initiated messages. Protocol revisions 2025-06-18 and 2025-03-26.
POST https://pangea.app/api/mcp Authorization: Bearer ph_live_…
API keys are issued by Pangea — there is no self-serve signup yet. Email adam@pangea.app with who you are and what you're building. You see the full key exactly once; we store only a hash, and revocation is immediate. Your key scopes everything: threads and candidate ids created by other integrators — or by Pangea's own chat product — don't exist as far as your key can tell.
Add the server
Claude Code:
claude mcp add --transport http pangea-hire https://pangea.app/api/mcp \ --header "Authorization: Bearer ph_live_YOUR_KEY"
Claude Desktop, Cursor, or any MCP client that speaks streamable HTTP — add to your client's MCP config (claude_desktop_config.json, .mcp.json, etc.):
{
"mcpServers": {
"pangea-hire": {
"type": "http",
"url": "https://pangea.app/api/mcp",
"headers": {
"Authorization": "Bearer ph_live_YOUR_KEY"
}
}
}
}Or raw JSON-RPC, if you're building the client yourself:
curl -s https://pangea.app/api/mcp \
-H "Authorization: Bearer ph_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {
"name": "search_talent",
"arguments": {
"thread_id": "<from start_hiring_thread>",
"title": "Senior Data Scientist",
"category": "Data Science & Analytics",
"description": "Forecasting models for a B2B logistics platform; Python, dbt, production ML.",
"budget_hourly_max": 110
}
}
}'Eleven tools, one loop
In the order a hire actually flows. Every tool after start_hiring_thread takes the thread_id it returned; responses carry both readable text and structuredContent.
start_hiring_threadCreate the container for one hiring conversation; optionally attach the client's email and company domain.
enrich_companyGround the thread in who the company is — scrape a domain, or store a summary you already have.
search_talentSearch the talent database; returns up to 5 anonymized, fit-scored candidate cards with all-in pricing.
refine_searchAdjust budget, seniority, category, or context and re-run; previously shown candidates excluded by default.
set_interestRecord your user's interested/passed decision on a candidate, with an optional reason.
register_clientAttach the human client and email them a verification link — unlocks outreach and hiring.
request_outreachAsk Pangea to invite flagged candidates to interview with your user.
get_pipelineThe authoritative funnel state: interested → invited → booked → interviewed → hire.
get_interviewsEvery interview on the thread with times, statuses, and video links.
get_thread_stateResume primitive: stage, summary, live role_spec_id, requirements, and decisions in one call.
start_hire_intentGenerate a hosted payment-setup link (no charge) to relay to your user at hire time.
Two read-only resources ride along: pangea://categories (the 10 canonical role categories search_talent requires, verbatim) and pangea://pricing-policy (the fee formula and display rules, machine-readable).
What a search returns
search_talent answers with up to five candidate cards — anonymized, fit-scored by an evidence-citing rerank stage, and priced all-in. This is the only candidate shape the API ever returns:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [{ "type": "text", "text": "5 candidates (of 42 considered). …" }],
"structuredContent": {
"role_spec_id": "3f6a1c9e-…",
"total_candidates_considered": 42,
"rerank_applied": true,
"weak_matches": false,
"candidates": [
{
"candidateShownId": "b9a1c2d3-…",
"displayName": "Maya R.",
"headline": "ML engineer — forecasting & pipelines",
"photoUrl": "https://img.pangeamart.com/production/640x640/….jpg",
"location": "Lisbon, Portugal",
"yearsExperience": 8,
"isTopTalent": true,
"overallRating": 4.9,
"paidContractCount": 23,
"skills": ["Python", "dbt", "Time-series forecasting"],
"fitReason": "Built demand-forecasting models for a freight marketplace — directly matches the logistics brief.",
"fitScore": 87,
"pricing": {
"talentRate": 80,
"clientRate": 92.00,
"feePercent": 0.15,
"rateEstimated": false,
"basis": "profile rate"
}
}
// …4 more cards. First name + last initial, always.
]
}
}
}candidateShownId is the handle everything downstream uses — set_interest, request_outreach, start_hire_intent. If weak_matches is true, every candidate scored below the fit floor and the best available were shown anyway — tell your user that honestly.
Enforced server-side, not vibes
Pricing is transparent, always
Every card carries the full breakdown: talent rate + 15% Pangea fee = all-in rate. client_rate = round(talent_rate × 1.15, 2). Show your user all three numbers; label rateEstimated: true rates as estimates. Talent keep their full rate.
Candidates are anonymized
First name + last initial, photo, headline, skills, stats. Tool responses never contain emails, full names, or profile links — before or after a hire. Contact flows through Pangea invites.
Real people, real consent
Outreach requires a verified human client email on the thread, and first sends typically pass Pangea's review valve. Talent may decline or stay silent — and booking is always the talent's own click, never the API's.
Silence is a count, not a name
Pipeline responses only name talent who actually responded or booked. Unanswered invites appear as an aggregate count. Don't tell your user a specific person is "considering it" — you don't know that.
Rate limits and quotas
Honest numbers, stated up front. Daily quotas are per key, reset at 00:00 UTC, and can be raised — ask. Hitting one returns a structured quota_exceeded error that says when to retry.
| Limit | Default | When hit |
|---|---|---|
| Burst | 10 tool calls / min | HTTP 429 + Retry-After |
Searches (search_talent + refine_search) | 50 / day | quota_exceeded |
| Outreach invites | 25 / day | quota_exceeded |
| Distinct candidates shown (anti-scraping) | 500 / 30 days | quota_exceeded |
| Open invites per talent (all clients) | 3 unanswered | candidate skipped with talent_cooldown |
Tool failures come back as MCP tool results with isError: true and structuredContent.error = { code, message, how_to_fix? }. Codes: unauthorized, quota_exceeded, thread_not_found, not_thread_owner, verification_required, invalid_state, upstream_timeout, talent_cooldown, invalid_input, internal_error.
Push, if you want it
Optional: Pangea can POST signed events to your endpoint — client.verified, invite.sent, invite.declined, invite.booked, booking.cancelled, interview.completed. Signature header x-pangea-signature: t=<unix>,v1=<hex> (HMAC-SHA256 over "t.body"; reject timestamps older than 5 minutes). Delivery is best-effort — get_pipeline is the authoritative state; treat webhooks as a poll accelerator, not a ledger. Endpoints are registered by Pangea for now — ask when you get your key.
Get a key, start hiring.
Full reference: pangea.app/api.md (markdown, agent-friendly) · machine orientation: /llms.txt · keys: adam@pangea.app. Hiring as a human instead? The composer on the front page is live.