open-greenhouse-mcp
# open-greenhouse-mcp
<!-- mcp-name: io.github.benmonopoli/greenhouse-mcp -->
[](https://pypi.org/project/open-greenhouse-mcp/)
[](https://github.com/benmonopoli/open-greenhouse-mcp/actions/workflows/ci.yml)
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
[](https://glama.ai/mcp/servers/benmonopoli/open-greenhouse-mcp)
Production-ready MCP server for Greenhouse, designed for recruiters and hiring teams.
Most Greenhouse MCP servers mirror the API endpoint by endpoint. This one is built for recruiting teams: safe defaults, role-based profiles, and workflow tools that turn multi-step API operations into single actions.
## Choose a Profile
| Profile | Tools | Can write? | Recommended for |
|---|---|---|---|
| `read-only` | 103 | No | First-time setup, reporting, hiring managers |
| `recruiter` **(default)** | 127 | Yes (safe ops) | Day-to-day recruiting work |
| `full` | 181 | Yes (all) | Admins, ops, advanced automation |
## Quick Start
```bash
pip install open-greenhouse-mcp
```
Add to your MCP client config (Claude Desktop: `~/Library/Application Support/Claude/claude_desktop_config.json`, Cursor: Settings > MCP):
```json
{
"mcpServers": {
"greenhouse": {
"command": "open-greenhouse-mcp",
"env": {
"GREENHOUSE_CLIENT_ID": "your-harvest-client-id",
"GREENHOUSE_CLIENT_SECRET": "your-harvest-client-secret",
"GREENHOUSE_TOOL_PROFILE": "read-only"
}
}
}
}
```
Start in read-only mode to validate connectivity and tool behaviour, then switch to `recruiter` or `full` when you need write access.
Your client ID and secret come from Greenhouse under Configure > Dev Center > API
Credential Management, created by someone with *Can manage ALL organization's API
Credentials*. Harvest v3 grants access **per endpoint**, so the credential needs
scopes for the endpoints you intend to use.
> **Harvest v3.** Harvest v1 and v2 became unavailable after 2026-08-31, so the
> older per-person `GREENHOUSE_API_KEY` no longer opens Harvest. Tools not yet
> verified against the v3 guides are withheld at startup rather than left
> registered and broken — see [docs/harvest-v3-migration.md](docs/harvest-v3-migration.md).
## What You Can Ask
- "Show me the pipeline for our Senior Engineer role"
- "Who needs my attention this week?"
- "What are our conversion rates for the Backend Intern role?"
- "Find Sarah Chen and pull up her resume"
- "Which sources are actually producing hires?"
- "Bulk reject everything inactive for 30+ days on the Account Manager role"
- "Screen this candidate for the Backend Engineer role — give me the full picture"
- "Search our engineering pipelines for anyone with Rust and distributed systems experience"
- "What new applications came in since yesterday?"
See [more examples with full output](docs/examples.md).
### See it in action

## Safety
- Access is limited by your Greenhouse API key permissions
- Read-only profile is recommended for first setup
- Destructive actions require explicit IDs — the server never infers targets
- Write operations support audit attribution via `GREENHOUSE_ON_BEHALF_OF`
- Bulk actions are rate-limited to stay within API limits
## Compatibility
| Client | Status |
|---|---|
| [Claude Desktop](https://claude.ai/download) | Supported |
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | Supported |
| [Cursor](https://docs.cursor.com/context/model-context-protocol) | Supported |
| Transport | stdio |
| Python | 3.10+ |
## Startup
When the server starts, it logs its configuration:
```
open-greenhouse-mcp v0.4.0
Profile: recruiter | Tools: 127 | Writes: recruiter-safe | APIs: harvest, ingestion
```
## What's Included
- **Screening & sourcing tools** — 6 tools for candidate screening, resume search with boolean keywords, daily digest, and location detection
- **Recruiter workflow tools** — 13 composite tools for pipeline views, analytics, search, and bulk operations
- **Harvest API coverage** — 148 tools across candidates, applications, jobs, offers, interviews, and more
- **Job Board API** — 13 tools for public job listings and application submission
- **Optional webhooks and ingestion** — 14 tools for event-driven workflows and partner integrations
---
## Reference
### Screening & Sourcing Tools
Tools for candidate evaluation and proactive talent search.
| Tool | What it does |
|---|---|
| `screen_candidate` | Complete screening package — profile, resume text, location, screening answers, job description, history |
| `fetch_new_applications` | Applications since a date, grouped by job — the daily recruiter digest |
| `scan_pipeline_resumes` | Search resume text across pipelines with boolean keywords (required/preferred/exclude) |
| `search_pipeline_candidates` | Search pipelines by structured fields — title, company, education, experience, tags |
| `scan_all_candidates` | Database-wide candidate search by structured fields with date bounds |
| `batch_read_resumes` | Batch-fetch and extract resume text for multiple candidates |
### Composite Tools
High-level tools that combine multiple API calls into single operations.
| Tool | What it does |
|---|---|
| `pipeline_summary` | Full pipeline view — candidates grouped by stage with names and days-in-stage |
| `candidates_needing_action` | Find stale applications and interviews missing scorecards |
| `stale_applications` | Applications with no activity for N days, sorted by stalest |
| `pipeline_metrics` | Conversion rates, hire/rejection rates, time-in-stage per stage |
| `source_effectiveness` | Which candidate sources produce the best hire rates |
| `time_to_hire` | Average, median, min, max days from application to hire |
| `bulk_reject` | Reject multiple applications in one call with rate-limit handling |
| `bulk_tag` | Tag multiple candidates in one call |
| `bulk_advance` | Advance multiple applications to next stage |
| `search_candidates_by_name` | Find candidates by first or last name |
| `search_candidates_by_email` | Look up a candidate by exact email |
| `read_candidate_resume` | Download and return a candidate's most recent resume |
| `download_attachment` | Download any Greenhouse attachment by URL |
### Profile Details
**Recruiter** includes all read tools, all screening/sourcing tools, all composite workflows, and recruiter-safe writes: reject, advance, hire, move, tag, notes, attachments, interviews, prospects, and bulk operations. It excludes job creation, user management, custom field configuration, candidate deletion, and webhook management.
**Read-only** skips all write operations. `GREENHOUSE_READ_ONLY=true` also works as a shorthand.
### Configuration
| Variable | Required | Description |
|---|---|---|
| `GREENHOUSE_CLIENT_ID` | Yes* | Harvest v3 client ID |
| `GREENHOUSE_CLIENT_SECRET` | Yes* | Harvest v3 client secret |
| `GREENHOUSE_USER_ID` | No | Your Greenhouse user ID — attributes v3 calls and derives the tool profile |
| `GREENHOUSE_BOARD_TOKEN` | Yes* | Job board URL slug. *Client credentials or a board token required |
| `GREENHOUSE_API_KEY` | No | Legacy v1 key — Job Board / Ingestion APIs only, not Harvest |
| `GREENHOUSE_ALLOW_UNMIGRATED_TOOLS` | No | Set `1` to register Harvest tools not yet verified against v3 |
| `GREENHOUSE_STRICT_PROJECTION` | No | Set `1` to fail (not warn) when a payload field is missing |
| `GREENHOUSE_TOOL_PROFILE` | No | `recruiter` (default), `read-only`, or `full` |
| `GREENHOUSE_ON_BEHALF_OF` | No | Greenhouse user ID for write audit trail |
| `GREENHOUSE_LOG_LEVEL` | No | `debug`, `info`, `warning` (default), `error` |
| `GREENHOUSE_LOG_FILE` | No | Log file path (defaults to stderr) |
| `GREENHOUSE_MAX_RESULT_BYTES` | No | Tool-result size budget in bytes (default `60000`) |
| `GREENHOUSE_DIAGNOSTICS_FILE` | No | Diagnostics file path (defaults beside Claude's logs) |
| `GREENHOUSE_DIAGNOSTICS` | No | Set `off` to disable the diagnostics file |
### Logging
Structured JSON logging for observability. Set `GREENHOUSE_LOG_LEVEL=info` to enable:
```json
{"ts": "2026-04-14T12:31:58", "level": "info", "event": "api_call", "method": "GET", "url": "...", "status": 200, "latency_ms": 245.0}
```
### More Documentation
- **[API Reference](docs/api-reference.md)** — Full tool breakdown by category
- **[Usage Examples](docs/examples.md)** — Real conversations with full output
- **[Advanced Setup](docs/advanced.md)** — Webhook receiver, ingestion API, board-token mode
- **[Development](docs/development.md)** — Contributing, testing, project structure
- **[Handoff](docs/HANDOFF.md)** — start here: current state, the verified v3 contract, and the traps that cost real records to find
- **[Harvest v3 migration](docs/harvest-v3-migration.md)** — full endpoint detail. Reads are verified live; writes are not, and 121 tools stay withheld until they are
## Changelog
Current version: **0.5.5**. Full detail for every release lives in
[CHANGELOG.md](CHANGELOG.md); this is the short version.
### 0.5.5 — reliability and error reporting
Aimed at deployments where the people using the tools are recruiters, not
engineers, so a failure has to be self-explanatory and reportable.
- **Result-size shaping** — results are measured and kept within a size budget
(60KB default, `GREENHOUSE_MAX_RESULT_BYTES` to override). A 500-job `/jobs`
page runs to ~1.1MB and clients reject an oversized tool result outright, so
the user saw a bare failure instead of an answer. Shaping degrades lazily:
untouched if it already fits, then field projection, then text clamping, then
dropping rows — attaching `returned`/`total_found` and a note telling the model
to narrow by a real filter or walk pages, rather than telling the user about
flags. Composite tools calling `list_*` internally still get complete data.
- **User-relayable errors** — every failure carries a plain-English
`user_message`, a `support_code` like `GH403-0730-1421-7F2D` the user can paste
into a support request, and `user_can_resolve` to separate "check the spelling"
from "escalate, you cannot fix this".
- **Always-on diagnostics file** — notable events append to a JSON-lines file at
a fixed path, so support is "send me this file" instead of asking a recruiter
to reproduce with logging turned up. `GREENHOUSE_DIAGNOSTICS=off` to disable.
- **Default profile is now `recruiter`, not `full`** — an unset or unrecognised
`GREENHOUSE_TOOL_PROFILE` used to register every tool with writes enabled,
including destructive ones. Explicit values, including `full`, are unchanged.
- **Fixed: 400 and 409 responses were treated as success data** — only an
enumerated set of statuses became errors, so a rejected filter value came back
looking like a real record. Any status >= 400 is now an error.
### 0.4.0 — screening and sourcing
`screen_candidate`, `fetch_new_applications`, `search_pipeline_candidates`,
`scan_all_candidates`, `batch_read_resumes`, and `scan_pipeline_resumes`, plus
server-side PDF/DOCX resume text extraction and a 5-step location detection
cascade.
### 0.3.0 — profiles and logging
Tool profiles via `GREENHOUSE_TOOL_PROFILE` (full / recruiter / read-only) and
structured JSON logging with per-call method, status, and latency.
### 0.2.1 — packaging
PyPI metadata: keywords, classifiers, and project URLs.
### 0.2.0 — composite tools
13 composite tools for recruiter workflows.
### 0.1.0 — initial release
Harvest, Job Board, and Ingestion API coverage.
## Skills
`skills/` holds the Claude skills that drive these tools for recruiters — application
triage, candidate screening, pipeline search, and resume batch review. Skills are
distributed separately from the extension bundle: upload each directory to Claude as
a skill, alongside installing the `.mcpb`.
They name MCP tools in prose, so a rename or a tool dropped from the bundle's pinned
profile would break them silently, at the moment a recruiter tried to use one.
`tests/test_skills.py` matches the registered tool set against each skill's text and
fails the build instead. Cited tools are discovered from the files rather than a
hardcoded list, so newly cited tools are covered automatically.
## Relationship to upstream
This project began as a fork of
[benmonopoli/open-greenhouse-mcp](https://github.com/benmonopoli/open-greenhouse-mcp)
(MIT, Copyright © 2026 Ben Monopoli), which remains the origin of the great majority
of this code. The `LICENSE` file is unchanged and continues to carry that notice.
Changes made here, released as 0.5.5:
- Result-size shaping, so a large tool result is trimmed to fit rather than rejected
- User-relayable error messages carrying a support code a non-technical user can pass on
- An always-on diagnostics file, so support does not depend on reproducing a failure
- A curated `assistant` tool profile, and a safe default profile instead of `full`
- A fix for error statuses being treated as success data
- An upper bound on `mcp`, without which a clean install resolves 2.0.0 and the
package cannot be imported at all
- A release workflow producing a cross-platform Claude Desktop bundle
To pull in future upstream work:
```sh
git remote add upstream https://github.com/benmonopoli/open-greenhouse-mcp.git
git fetch upstream && git merge upstream/main
```
## Feedback
- **Bugs and features:** [Open an issue](https://github.com/benmonopoli/open-greenhouse-mcp/issues)
- **Questions:** [Start a discussion](https://github.com/benmonopoli/open-greenhouse-mcp/discussions)
- **Security:** See [SECURITY.md](SECURITY.md)
- **Contributing:** See [CONTRIBUTING.md](CONTRIBUTING.md)
## License
MIT License -- Ben Monopoli. See [LICENSE](LICENSE).
TDQS
Scored across 33 tools
Most tools target distinct resources and actions, and descriptions include routing hints that clarify when to use each one. Some overlap exists among application-listing tools (list_applications, fetch_new_applications, stale_applications, pipeline_summary) and resume-search tools, but the intended boundaries are mostly clear.
The majority of tools follow a snake_case verb_noun pattern like list_jobs, get_candidate, and reject_application. A few analytic tools break the pattern (pipeline_summary, source_effectiveness, time_to_hire, candidates_needing_action), and there is some verb variation across list/fetch/search/read, but the overall convention is predictable.
33 tools is a heavy surface for an MCP server, exceeding the 25+ threshold where the set becomes difficult for an agent to navigate. While the ATS domain is broad, several tools overlap in capability and could be consolidated or omitted.
There are significant gaps, including referenced tools that do not exist in the set: list_tags, list_email_templates, and move_application_same_job are mentioned in descriptions but unavailable. There are also no create/update operations for candidates or jobs, and add_tag_to_candidate depends on a missing tag-listing tool, which will cause agent failures.