Skip to main content
Glama
DINQ-labs

openpeoplerouter

Official
by DINQ-labs
README.md
# OpenPeopleRouter

**An open-source MCP server that finds people and companies through the data
providers you already pay for.** Bring your own keys; nothing goes through a
middleman.

- **7 job tools** an agent can call without knowing any provider: `find_people`,
  `enrich_person`, `find_contact`, `verify_email`, `find_companies`,
  `enrich_company`, `read_profile`.
- **68 providers, 2,200+ operations** — B2B people and company data, email
  finding and verification, phone data, research and developer profiles, social
  platforms, web search and scraping. See [docs/providers.md](docs/providers.md).
- **Your keys, your bills.** Each provider bills your own account. Keys stay in
  your environment and are scrubbed from every response.
- **One YAML file per provider.** Adding one needs no Python.

[中文说明](README.zh-CN.md) · [Provider list](docs/providers.md) · [Provider file format](docs/provider-format.md) · [How routing works](docs/architecture.md)

## Run it

Requires Python 3.11+ and [uv](https://docs.astral.sh/uv/).

```bash
git clone https://github.com/DINQ-labs/openpeoplerouter && cd openpeoplerouter
uv sync
cp .env.example .env          # fill in only the providers you use
uv run openpeoplerouter providers
uv run openpeoplerouter run find_contact "full_name=Jane Doe" company_domain=example.com
```

Several sources work with no key at all (OpenAlex, ORCID, Crossref, Wikidata,
GitHub, Hugging Face, Semantic Scholar, Stack Exchange, Bluesky), so the server is
useful before you configure anything.

### In an MCP client

The default transport is stdio:

```json
{
  "mcpServers": {
    "openpeoplerouter": {
      "command": "uv",
      "args": ["--directory", "/absolute/path/to/openpeoplerouter", "run", "openpeoplerouter", "serve"]
    }
  }
}
```

Over HTTP, for a server you share with your own tools:

```bash
OPENPEOPLEROUTER_TOKEN=change-me uv run openpeoplerouter serve --transport http --host 0.0.0.0 --port 8080
```

Clients then connect to `http://host:8080/mcp` with `Authorization: Bearer change-me`.
The server refuses to listen beyond localhost without a token, because it spends
your provider credits. `docker compose up` does the same in a container.

## Tools

| Tool | What it does |
| --- | --- |
| `find_people` | People by title, employer, place, skills or a description. `audience` picks professionals (default), researchers, developers or creators. Rows from several providers are merged and de-duplicated. |
| `enrich_person` | One person from an email, LinkedIn URL, phone, or name with employer. |
| `find_contact` | Work email and phone for one person. |
| `verify_email` | Whether an address can receive mail. |
| `find_companies` | Companies by industry, place, size, technology or a description. |
| `enrich_company` | One company from its domain, name or LinkedIn page. |
| `read_profile` | One public profile on LinkedIn, X, Instagram, TikTok, YouTube, GitHub, Bluesky, Threads and more. |
| `providers` | What is configured, and which variable each provider reads. |
| `search_operations` | Find any provider operation by words. |
| `describe_operation` | Its parameters, price and docs. |
| `call_operation` | Run it with the provider's own parameters and get the raw response. |

Every job result lists what was `tried`: the operation, whether it answered, how
long it took, and the error if it failed — so an agent can tell "nobody matched"
from "the key was rejected" from "out of credit".

## Choosing providers

```dotenv
# Only these providers may be called (default: every provider with a key, plus keyless ones)
OPENPEOPLEROUTER_PROVIDERS=hunter,apollo,openalex
# Try these first, in this order; the rest follow, cheapest first
OPENPEOPLEROUTER_ORDER=apollo,hunter
```

A job call can also pass `providers: ["pdl", "lusha"]` to use only those, in that
order, and `raw: true` to get each provider's full record next to the mapped
fields.

## Command line

```bash
openpeoplerouter serve [--transport stdio|http] [--host] [--port]
openpeoplerouter providers [--markdown]
openpeoplerouter check                     # validate every provider file
openpeoplerouter run <job> key=value ...    # run a job once
openpeoplerouter call <provider.operation> key=value ...
```

Values that parse as JSON are sent as JSON (`limit=5`, `filters='{"x":1}'`).

## Adding a provider

Write `src/openpeoplerouter/providers/<id>.yaml` as described in
[docs/provider-format.md](docs/provider-format.md). For APIs with an OpenAPI
document, `scripts/from_openapi.py` drafts the operations. Run
`openpeoplerouter check` and `uv run pytest`, then open a pull request.

Provider definitions describe each provider's public API documentation. Most
routes were checked against those documents and response schemas; keyless and
test-key providers were also called live. If a provider changed its API, the
fix is usually one line in its file.

## Responsible use

You are responsible for using each provider within its terms and the law where
you and the people you look up are, including data-protection rules such as the
GDPR and CCPA. Some providers carry their own restrictions (for example, phone
data that is not a consumer report and must not be used for credit, insurance,
employment or housing decisions).

## License

Apache-2.0

TDQS

A3.7/5.0

Scored across 12 tools

Disambiguation4/5

The people_* family is mostly distinct, but social_profile, people_enrich, and people_identity_resolve all accept a single person identifier and return profile-related data, so an agent needs to read descriptions carefully. The meta tools (find_tool, endpoint, call_tool) are clearly separated.

Naming Consistency4/5

Most domain tools follow a clear people_/companies_ prefixed snake_case pattern. Minor deviations include social_profile lacking the people_ prefix and meta tools mixing noun forms (capabilities, endpoint) with verb_noun forms (find_tool, call_tool).

Tool Count5/5

12 tools is well within the ideal range for a multi-provider data router: 8 domain operations plus 4 discovery/execution tools. Each tool has a clear role, and none feel redundant.

Completeness5/5

People workflows are comprehensively covered: search, social profile, enrich, identity resolution, contact finding, and image-based lookup. Companies have search and enrich, and the capabilities/find_tool/endpoint/call_tool layer prevents dead ends by allowing access to provider-specific endpoints.

Maintenance

ActivityMaintained
ResponsivenessNo issues