---
name: peoplerouter
description: Find, enrich and reach people through PeopleRouter — broad data coverage across dozens of providers, cost-aware routing and automatic fallback through one MCP endpoint. Use when a user asks to find engineers, researchers, founders, maintainers, candidates or a company's team; to fill in a person you can already identify; to resolve one profile into all of someone's accounts; or to get a work email or phone. Name the job, not the vendor.
version: 0.3.0
---

# PeopleRouter

PeopleRouter gives AI agents broad access to people data through one MCP connection. It brings
together dozens of providers across B2B people and company data, developer communities, academic
research and social platforms. A unified set of tools covers discovery, enrichment, identity
resolution and contact lookup, with complementary sources available for different research needs.

Cost-aware routing, automatic provider fallback and per-call credit budgets help agents complete
people-search workflows efficiently. PeopleRouter handles provider integrations, authentication,
response normalization and call tracking, reducing the work of operating separate data services.

**Ask for a job, not a vendor.** Every people-search vendor worth using is in one catalog here, filed
under the job it answers. You say what you want to learn and what you know about the subject; the
router picks the vendors that can answer, orders them by what an answer actually costs, and asks them
one at a time until one has it. You never name a vendor, and you never need to know which site holds
the answer.

## Connect (once)

```text
MCP (Streamable HTTP):  https://mcp.peoplerouter.ai
```

**Sign-in is OAuth.** The endpoint answers 401 with resource metadata; the client discovers the DINQ
authorization server, registers itself, and opens a browser for the user to sign in once. The token
refreshes itself afterwards. Do not ask the user for an API key. If you are the agent setting this up:
add the server, start the login, and when the browser opens tell the user to sign in and wait.

```bash
# Claude Code
claude mcp add --transport http peoplerouter https://mcp.peoplerouter.ai && claude mcp login peoplerouter
# Codex CLI (add only writes the config; login opens the browser)
codex mcp add peoplerouter --url https://mcp.peoplerouter.ai && codex mcp login peoplerouter
# Gemini CLI (opens the browser on the first 401)
gemini mcp add --transport http peoplerouter https://mcp.peoplerouter.ai
# Cursor / Windsurf / VS Code: {"url": "https://mcp.peoplerouter.ai"} under mcpServers; the client opens the browser
```

Then call `capabilities()`: it costs nothing and proves the connection. A 401 means the sign-in did
not finish; run the login step again.

Unattended agents and SDKs, which cannot open a browser, pass a DINQ key instead:
`Authorization: Bearer sk-…` (Codex: `bearer_token_env_var` in config.toml). Clients that cannot send
headers (Claude app, ChatGPT connectors) use `https://mcp.peoplerouter.ai/u/<DINQ_API_KEY>/mcp`. The vendor credentials
are the server's, not yours.

## The jobs

One tool per job. Its parameters are the contract, so the schema itself tells you which combinations
of identifiers name a subject. Which of them are switched on depends on the keys this server holds;
`capabilities()` says which, and what each costs.

| tool | what it answers | identify the subject with |
|---|---|---|
| `people_search` | A list of people you did not have | {q} · {company_domain} · {company_domain + title} · {title} · {full_name} · {source_url} · {company_name} |
| `companies_search` | Find companies by industry, size or technology | {q} · {name} · {industry} · {technology} · {domain} |
| `people_enrich` | Fill in a person from an identifier you already hold | {email} · {linkedin_url} · {linkedin_handle} · {domain + full_name} · {domain + first_name + last_name} · {scholar_url} · {x_handle} · {github_url} · {company + full_name} |
| `companies_enrich` | Turn a company name or domain into its facts | {domain} · {website} · {name} · {linkedin_url} · {linkedin_handle} · {email} |
| `people_from_image` | A photo in, the person out | {image_url} |
| `social_profile` | One person's public profile on whatever platform a handle belongs to | {profile_url} · {handle + platform} |
| `people_identity_resolve` | One person's profiles across platforms, resolved into a single set | {email} · {linkedin_url} · {github_url} · {x_handle} · {scholar_url} · {huggingface_url} · {company + full_name} · {domain + full_name} |
| `people_contact_find` | How to reach one person | {domain + full_name} · {domain + first_name + last_name} · {linkedin_url} · {linkedin_handle} · {company + full_name} · {email} |

Two more tools describe the catalog itself, and neither costs anything:

| tool | in | out |
|---|---|---|
| `capabilities(capability?)` | nothing, or one capability | what each job answers, which identifiers name the subject, which vendors serve it here and what each costs |
| `endpoint(endpoint_id)` | one vendor endpoint id | what it accepts, costs, how long it takes, what counts as a miss |

## What to read in the answer

* `plan.will_try` — the order, decided before anything was called, with the credits each would cost.
* `_dinq.tried` — what each vendor actually answered, what it cost, and why the router moved on.
* `_dinq.served_by` — who answered. Name it when you present the result.
* `raw` — the vendor's own payload, for fields the contract does not carry.
* `outcome: miss` — everyone was asked and nobody has it. That is an answer; do not retry the same
  identity.

**A miss is free.** Most vendors here bill only when they find something, so walking down the list
costs nothing until one of them answers. Set `max_credits` to cap a call; the router skips anything
that would break the ceiling and says so. `vendor="<id>"` pins one vendor when you have a reason;
leaving it out is almost always right.

While a call runs the server streams one line per vendor — `apollo: asking…`, `contactout: hit · 2
emails · 3 credits · 1.4 s` — through MCP progress notifications. Surface it if your client shows it.

## The procedure

1. **Pick the job by what you want to learn**, never by which site might hold it. Whether the answer
   comes from LinkedIn, Apollo or a scrape is the router's decision, not yours.
2. **Give everything you hold.** More identifiers means more vendors can answer and the match is
   surer. A bare name is rarely enough; a name plus the employer's domain usually is.
3. **Chain the jobs.** A company name becomes a domain with `companies_enrich`, and that domain plus a
   name is exactly what `people_contact_find` wants. A source URL becomes people with `people_search`,
   and each of those becomes an email the same way. One profile becomes all of someone's accounts with
   `people_identity_resolve`.
4. **Cross-reference before you assert.** One vendor is a lead; the same person from two is a match.
5. **Cite who answered** (`_dinq.served_by`) for every fact, and say plainly when nobody had it.
6. **Show the work.** Before a slow call, say what you are about to do. After it, one line per
   `tried[]` row. The search should read as vendors lighting up, not as a silent pause.

## Read the answer, not the error

Routed tools never throw. Branch on `outcome` and on `_dinq.tried[].error.code`:

| code | means | do |
|---|---|---|
| `needs_identifier` | not enough to name the subject | the error lists the combinations that work; get one, do not guess |
| `bad_input` | the value is not what this job accepts | fix the input; never retry it against a different job |
| `not_found` | nothing lives at that address | web-search the current URL, then retry |
| `missing_credential`, `credential_rejected` | this server cannot reach that vendor | the router already moved on; not your fault |
| `rate_limited`, `timeout`, `provider_error` | the vendor failed | the router already tried the next one |
| `vendor_exhausted` | that vendor's own account is out of credit | ours to fix, not yours |
| `needs_key` | no vendor for that job is switched on here | send the user to the `connect` URL in the error |
| `insufficient_credits` | the DINQ account is out of credits | send the user to the `topup` URL |
| outcome `miss` | every vendor answered "nothing" | read `tried[].note`: a renamed repo, an empty Scholar shell and a private LinkedIn profile all *look* like success |

## Account and cost

Calls carry a DINQ key: `Authorization: Bearer sk-…` (Claude Code `--header`, Cursor and VS Code
`headers`, SDKs) or the `/u/<key>/mcp` URL for clients that cannot set headers. Credits are charged
per **hit**; misses and errors cost nothing. Every answer reports `_dinq.credits` (this call) and
`_dinq.balance` (after it). Never ask for the key in chat; hand the user the `connect` URL from the
error and let them add it to their client.

Prices differ by an order of magnitude across the catalog, and a phone number costs several times an
email. The router already ranks by what an answer actually costs, so the useful lever is `max_credits`
on calls you expect to be speculative. Every tool is read-only; run independent calls concurrently.

## Web search: to find the door, never to read the room

Use your own web search to find the **entry URL**, then hand that URL to a job. Do not read a person's
data out of search snippets, and do not open these hosts yourself:

| host | what happens if you fetch it directly |
|---|---|
| linkedin.com | login wall — an empty shell or a sign-in page, which reads like "no profile" |
| scholar.google.com | bot check page |
| x.com / twitter.com | client-rendered — no content |
| crunchbase.com | bot check plus paywall |

Search patterns that find the URL quickly:

| looking for | query |
|---|---|
| a person's LinkedIn | `site:linkedin.com/in "Full Name" Company` |
| a person's Scholar profile | `"Full Name" google scholar` |
| a person's GitHub | `site:github.com "Full Name"` |
| the key projects in a field | `best open source <topic> github` |
| a company's LinkedIn page | `site:linkedin.com/company <company>` |

Stop at the URL. The tools do the reading.

## What is not here

Personal sites, conference talks, patents, theses, lab and faculty pages, company team pages, and
Chinese-language sources (Zhihu, 36Kr, 掘金, 脉脉, WeChat articles). Cover them with your own web
search; they hold contact details and context no vendor here returns.
