{
  "markdown": "<!-- mcp-name: io.github.gzchenhao/openhire -->\n\n# OpenHire · 开聘\n\n> **A job-search radar for your AI assistant — first-party listings, ghost jobs scored, and your résumé never touches our servers.**\n> 让 AI 助手替你盯岗的求职雷达 —— 一手职位、幽灵岗位打分，简历不经过我们的服务器。\n\n![MCP 1.0](https://img.shields.io/badge/MCP-1.0-58A6FF) ![privacy: local-first](https://img.shields.io/badge/privacy-local--first-3FB950) ![python ≥ 3.11](https://img.shields.io/badge/python-%E2%89%A5%203.11-C9D1D9) ![license: MIT](https://img.shields.io/badge/license-MIT-C9D1D9) ![139 employers](https://img.shields.io/badge/employers-139-E3B341) [![OpenHire on Glama](https://glama.ai/mcp/servers/gzchenhao/openhire/badges/score.svg)](https://glama.ai/mcp/servers/gzchenhao/openhire)\n\n<p align=\"center\"><img src=\"docs/quickstart.svg\" alt=\"30-second quickstart: pipx install openhire, ohp bootstrap, ohp search\" width=\"880\"></p>\n<p align=\"center\"><sub>Real terminal output — install from PyPI, download the public index, search. No account, no signup.</sub></p>\n\nAn MCP server that turns your AI assistant (Claude, Cursor, Windsurf) into a private radar for\n**AI / Infra, autonomous-driving and embodied-AI jobs** — pulled straight from **139 employers'**\nown career sites and public ATS APIs (Greenhouse / Lever / Ashby / 北森 Beisen / Moka), across\nthe US, Europe **and China** (Waymo, Figure, Zoox — and Unitree, XPeng, UBTECH, Mech-Mind…).\n**No account. No signup. No résumé upload. Ever.**\n\nThree things a job board won't do for you:\n\n- **Kills ghost-job noise.** Every listing carries a `ghost_score` aged off the employer's\n  **real** posting date — the \"2 days ago\" a board shows you can be 300 days old in the ATS.\n- **Structural privacy, not a pinky-promise.** There is no résumé field in the protocol; a CI\n  test fails the build if anyone adds one. Matching runs on your machine — only an anonymous\n  fingerprint reaches the server.\n- **Ranking you can't buy.** Order is a locked pure function of (match, freshness). No\n  sponsored slots, no bidding — the signature is frozen by a test.\n\nThis is the 「哨兵 / Sentinel」 reference implementation — see\n`design_handoff_openhire_v01/README.md` for the full protocol spec.\n\n---\n\n## Quickstart — under a minute\n\n```bash\n# 1. Install (pipx keeps it isolated and puts `ohp` on your PATH)\npipx install openhire\n\n# 2. Get a job index. Default: download the public snapshot, then refresh it live.\nohp bootstrap                    # 139 employers · ~16k live postings · no account\n\n# 3. Use it directly…\nohp search --required-skills rust,k8s --remote --role-family engineering\nohp search --currency CNY --role-family engineering   # e.g. CN autonomous-driving / robotics roles\n\n# …or connect it to an MCP client:\nohp serve\n```\n\nThen point your MCP client at it — see **[Works with](#works-with)** below.\n\n---\n\n## Works with\n\nAll clients use the same MCP entry. If you ran `pipx install openhire`, use `ohp`; otherwise\n`uvx openhire serve` fetches and runs it with no prior install (needs [uv](https://docs.astral.sh/uv/)).\n\n**Claude Desktop** — `%APPDATA%\\Claude\\claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/`); quit & reopen after editing:\n```json\n{ \"mcpServers\": { \"openhire\": { \"command\": \"ohp\", \"args\": [\"serve\"] } } }\n```\n\n**Cursor** — `~/.cursor/mcp.json` (or a project `.cursor/mcp.json`):\n```json\n{ \"mcpServers\": { \"openhire\": { \"command\": \"uvx\", \"args\": [\"openhire\", \"serve\"] } } }\n```\n\n**Windsurf** — `~/.codeium/windsurf/mcp_config.json`:\n```json\n{ \"mcpServers\": { \"openhire\": { \"command\": \"uvx\", \"args\": [\"openhire\", \"serve\"] } } }\n```\n\n> Run `ohp bootstrap` once first so the index has data. On Windows Claude Desktop from the\n> Microsoft Store, the config is under `…\\Packages\\<Claude package>\\LocalCache\\Roaming\\Claude\\`.\n\n---\n\n## What it does\n\n| Tool | What it gives you |\n|------|-------------------|\n| `search_jobs` | Hard-filter the live index; every result carries `verified_at`, `datePosted`, `days_open`, `ghost_score`, `remote_scope`, `eligible_regions`, `apply_channel`. Filter by `required_skills` (AND), `role_family`, `remote_scope`, `min_salary` + `currency`. |\n| `watch_intent` | Register a standing intent once — new matching jobs are waiting next time you check, even after you close the terminal. Accepts `required_skills` / `role_family` so sales / solutions roles stay out. |\n| `check_watches` | Pull the matches that are new since your last check (client-pull; stdio has no push). |\n| `authorize_application` | One explicit confirmation per job. It records your authorization and returns the employer's **own** application URL — you apply as yourself. It **cannot** accept a résumé. |\n| `get_company_info` | Aggregate, anonymous trust signals for one employer (`ghost_score_avg`, `active_jobs`, `index_built_at`). Never any candidate data. |\n\nOptional, entirely local: `ohp init --scan <dir>` derives a **skill fingerprint** from your\nown repos. You never write a résumé; the code never leaves your machine — only an anonymous\nvector does.\n\n## The five protocol fields\n\nEvery listing is valid `schema.org/JobPosting`, plus:\n\n- `verified_at` — last moment confirmed live on the employer's own site\n- `source` — `employer_site | ats_public_api` (never a job board)\n- `ghost_score` — 0–1 listing-activity signal, aged off the **real** posting date (lower =\n  fresher). A noise filter, not an accusation: long-open listings are often evergreen talent\n  pools or slow pipelines — the score simply lets agents down-rank low-activity noise\n- `response_sla_days` — employer's committed response window (v0.1: always null)\n- `apply_channel` — always the employer's own application URL, deep-linked to the specific job\n\n## Privacy model\n\n| | |\n|---|---|\n| **Résumé / PII upload** | **never** — matching runs locally; a résumé never transits the server, and we never store one |\n| **What the server sees** | one anonymous, client-generated fingerprint + hard filters |\n| **Repo scan** | local-only · personal projects · explicit consent · opt-out anytime |\n| **Job sources** | first-party only: employer career pages + public ATS APIs (Greenhouse / Lever / Ashby) |\n\n## First-run data — the snapshot vs. fresh\n\n`ohp bootstrap` (default) downloads a small **public** index snapshot (a GitHub Release\nasset — `companies` + `jobs` only, **zero** user data) and then runs one incremental crawl to\nrefresh `verified_at` / delisting. `--fresh` skips the snapshot and crawls the public ATS from\nscratch with the free offline heuristic extractor. Either way: no account, no PII.\n\n## Three rules this project will never break\n\n1. Your résumé stays on your machine — it never transits the server, and we never store it.\n2. Ranking is not for sale — it is only `f(match_quality, freshness)`, a locked pure function.\n3. Employers pay only for authorized, delivered outcomes — never for exposure. (v0.1 has no\n   billing at all.)\n\nThese are enforced by CI (`tests/test_privacy.py`, `tests/test_ranking.py`,\n`tests/test_snapshot.py`).\n\n## Development\n\n```bash\npython -m venv .venv && . .venv/Scripts/activate   # Windows\npip install -e \".[dev]\"\npytest        # privacy red lines + ranking + snapshot must be green\n```\n\nSet `OPENHIRE_DATABASE_URL=postgresql+psycopg://…` to run against Postgres instead of the\ndefault local SQLite file (`~/.openhire/openhire.db`).\n\n## Roadmap\n\n- **v0.2 – v0.3 (shipped)** — CN ATS adapters (北森 Beisen + Moka) · weekly auto-refreshed\n  public snapshot · `ghost_score` public beta · 139 employers across US / EU / China\n- **next** — Employer claim + verified badges — employers can [reserve their claim\n  today](https://github.com/gzchenhao/openhire/issues/new?template=employer_claim.yml) via a\n  corporate-identity GitHub issue (zero-cost now; badges + listing-status control ship next) ·\n  response-SLA enforcement (7-day auto-delist) · **redacted proof-of-fit** — an anonymous,\n  candidate-authorized match summary that travels with an application (skills overlap only;\n  identity never included, résumés still never transit the server)\n- **v1.0** — Open, vendor-neutral schema extension for AI-readable job postings\n\n## FAQ\n\n**Where does the job data come from?**\nDirectly from 139 employers' own public ATS APIs (Greenhouse, Lever, Ashby, 北森 Beisen, Moka) — the\nsame endpoints that power their careers pages. No scraping, no third-party job boards. `source` is\nalways `ats_public_api`, and `verified_at` records the last time we confirmed each posting live.\nThe public index is auto-refreshed weekly, so a fresh `ohp bootstrap` starts from recent data.\n\n**Why should I trust `ghost_score`?**\nIt's a pure, open, unpurchasable function — `min(1, 0.15·relist_count + staleness)` aged off the\n**real** ATS posting date, not our crawl date. The formula lives in `pipeline/ghost_score.py`,\nis unit-tested, and takes no money as input (red line #2). Long-open, repeatedly-relisted\npostings score higher; you can always re-rank client-side. Read it as **signal-to-noise, not\nbad faith**: plenty of high-scoring listings are legitimate evergreen talent pools. Employers\nwho want their listing activity represented accurately can claim their tenant (see Roadmap).\n\n**Does my résumé actually go through the server — really?**\nNo. There is no résumé anywhere in the protocol. `authorize_application` has no résumé/file\nparameter (it structurally cannot accept one), matching runs on your machine, and the only thing\nthat ever transits the server is a short anonymous fingerprint like `#a3f9`. This is enforced by\n`tests/test_privacy.py`, and the published snapshot carries **zero** user data (`tests/test_snapshot.py`).\n\n**Does it support China (中国区)?**\nYes — this is what sets OpenHire apart. Employers on **北森 Beisen** (`<tenant>.zhiye.com`) and\n**Moka** (`app.mokahr.com`) are indexed: 20+ autonomous-driving / robotics / embodied-AI\ncompanies including 宇树 Unitree, 小鹏 XPeng, 优必选 UBTECH, 梅卡曼德 Mech-Mind, 速腾聚创 RoboSense,\n元戎启行 DeepRoute, 星海图 Galaxea, 傅利叶 Fourier, 普渡 Pudu. Pay published as 月薪 keeps its real\nperiod (`salary_period`), so a salary floor no longer silently drops Chinese roles.\n\n**飞书招聘 (Feishu Hire) is not supported and won't be**: it signs its job-list requests with a\nByteDance `_signature` and gates them behind a captcha SDK, so its listings are not publicly\nreadable. We don't break anti-bot measures. Moka is on the roadmap.\n\n**How do I get a company added?**\nOpen a **Company inclusion request** issue (title it with the company + its ATS URL) — this is\nthe best way to contribute. If you code, add it to `src/openhire/seed/candidates.py` (company\nslug + ATS vendor/tenant) and open a PR; the seeder validates tenants against the live API.\n\n## License\n\nMIT © OpenHire Protocol · PRs welcome.\n\n---\n\n*Built by a non-coder PM-ing Claude Code — full acceptance reports in [`reports/`](reports/).*\n",
  "bytes": 10774,
  "sha": "a84783a512219ce7e7fb67ec42ae26eb19e91476d54274aed0c9bd684da57bbc",
  "repo_slug": "gzchenhao/openhire",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_gzchenhao_openhire_1925167c/readme"
}