Connect Greenhouse to Claude: Track Applications and Interviews
Learn how to connect Greenhouse to Claude using a managed MCP server. Automate candidate tracking, interview scheduling, and hiring workflows with AI.
If you need to connect Greenhouse to Claude to automate applicant tracking, interview scheduling, or candidate pipeline analysis, you need a Model Context Protocol (MCP) server. This server acts as the translation layer between Claude's tool calls and the Greenhouse Harvest API. You can either build and maintain this infrastructure yourself, or use a managed integration platform like Truto to dynamically generate a secure, authenticated MCP server URL.
If your team uses ChatGPT, check out our guide on connecting Greenhouse to ChatGPT or explore our broader architectural overview on connecting Greenhouse to AI Agents.
Giving a Large Language Model (LLM) read and write access to an Applicant Tracking System (ATS) like Greenhouse presents specific engineering challenges. You have to handle complex custom fields, parse nested candidate data, and deal with Greenhouse's specific rate limits. Every time an endpoint changes or you need to expose a new custom field, you have to update your server code, redeploy, and test the integration.
This guide breaks down exactly how to use Truto to generate a secure, managed MCP server for Greenhouse, connect it natively to Claude, and execute complex hiring workflows using natural language.
The Engineering Reality of the Greenhouse API
A custom MCP server is a self-hosted integration layer. While the open MCP standard provides a predictable way for models to discover tools, the reality of implementing it against the Greenhouse Harvest API requires navigating several strict vendor constraints.
If you decide to build a custom MCP server for Greenhouse, you own the entire API lifecycle. Here are the specific challenges you will face:
Header-Based Pagination vs LLM Cursors
The Greenhouse Harvest API does not use standard JSON body tokens for pagination. Instead, it relies on HTTP Link headers containing full URLs with page and per_page parameters (rel="next"). Large Language Models cannot read HTTP headers from a standard REST response. If you expose the raw Greenhouse API to Claude, the model will have no idea how to paginate through hundreds of candidates. Truto solves this by intercepting the Link header and normalizing it into standard limit and next_cursor properties injected directly into the JSON response payload. Truto's schemas explicitly instruct the LLM to pass these cursor values back unchanged on subsequent calls, enabling Claude to seamlessly paginate through long lists of applications.
Nested Custom Field Arrays
Greenhouse makes heavy use of custom fields for everything from demographic data to specific technical screening scores. However, these are not returned as flat key-value pairs. They are returned as arrays of objects (e.g., [{ "id": 12345, "name": "Technical Score", "value": "Strong Yes", "type": "string" }]). LLMs struggle to query or update arrays of objects without strict JSON Schema definitions guiding them. Truto automatically generates these schemas, defining exactly how Claude should structure its queries to filter or update custom field arrays without hallucinating incorrect data types.
Strict Rate Limits Greenhouse enforces a strict rate limit of 50 requests per 10 seconds. If an AI agent attempts to iterate through a list of 100 applications to extract resume data simultaneously, it will hit this limit almost immediately.
A factual note on rate limit handling: Truto does not retry, throttle, or apply backoff on rate limit errors. When the Greenhouse upstream API returns an HTTP 429 Too Many Requests, Truto passes that error directly back to the caller. However, Truto normalizes the upstream rate limit information into standardized headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) per the IETF specification. Claude, or your multi-agent framework, is responsible for reading these headers and executing its own backoff strategy. Do not expect the MCP server to absorb these errors silently.
How to Generate a Greenhouse MCP Server with Truto
Truto's MCP server feature turns your connected Greenhouse integration into an MCP-compatible tool server dynamically. Instead of hand-coding tool definitions, Truto derives them from Greenhouse's documented resource schemas. A tool only appears in the MCP server if it has a strict JSON schema and documentation entry - ensuring only well-defined endpoints are exposed to the LLM.
Each MCP server is scoped to a single integrated account. The server URL contains a cryptographic token that encodes which account to use, what tools to expose, and when the server expires.
You can generate this server via the Truto UI or programmatically via the API.
Method 1: Generating via the Truto UI
For administrators setting up a persistent connection for Claude Desktop:
- Log into your Truto dashboard and navigate to the integrated account page for your active Greenhouse connection.
- Click the MCP Servers tab.
- Click Create MCP Server.
- Select your desired configuration. You can name the server (e.g., "Greenhouse Recruiting Assistant") and restrict access. For example, select
readunder allowed methods to ensure Claude can only pull data and cannot accidentally update candidate statuses. - Copy the generated MCP server URL (e.g.,
https://api.truto.one/mcp/a1b2c3d4...).
Method 2: Generating via the API
For engineering teams dynamically provisioning MCP servers for individual users or automated RAG pipelines, you can generate the server via a simple POST request.
The API validates that the Greenhouse integration has documented tools available, generates a secure token, and returns a ready-to-use URL.
curl -X POST https://api.truto.one/integrated-account/{integrated_account_id}/mcp \
-H "Authorization: Bearer YOUR_TRUTO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Greenhouse Talent Assistant",
"config": {
"methods": ["read"],
"tags": ["recruiting", "candidates"]
}
}'The response provides the self-contained URL:
{
"id": "mcp_8a9b0c...",
"name": "Greenhouse Talent Assistant",
"config": { "methods": ["read"], "tags": ["recruiting", "candidates"] },
"expires_at": null,
"url": "https://api.truto.one/mcp/a1b2c3d4e5f6..."
}This single URL handles all authentication routing. The raw token is hashed before being stored in Truto's distributed key-value infrastructure, ensuring your credentials remain secure.
How to Connect the MCP Server to Claude
Once you have your Truto MCP URL, connecting it to Claude requires zero additional code. You can connect it via the Claude interface or through the manual configuration file.
Method 1: Via the Claude UI
If you are using Claude Desktop (or a similar interface like ChatGPT's Custom Connectors):
- In Claude Desktop, go to Settings -> Integrations.
- Click Add MCP Server (or "Add custom connector").
- Paste the Truto MCP URL you generated in the previous step.
- Click Add.
Claude will immediately ping the endpoint, execute the protocol handshake, and pull down the list of available Greenhouse tools.
Method 2: Via Manual Configuration File
If you are managing Claude Desktop deployments for a team, or using a CLI tool, you can add the server directly to your claude_desktop_config.json file.
Because Truto exposes MCP over HTTPS using Server-Sent Events (SSE) and standard JSON-RPC, you can use the official @modelcontextprotocol/server-sse transport wrapper.
{
"mcpServers": {
"greenhouse": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sse",
"https://api.truto.one/mcp/a1b2c3d4e5f6..."
]
}
}
}Restart Claude Desktop. The model now has direct, authenticated access to your Greenhouse instance.
Essential Greenhouse Tools for Claude
Truto exposes dozens of Greenhouse operations as discrete tools. During the tools/list protocol handshake, Truto dynamically derives the tool names, descriptions, and JSON Schemas from the integration documentation.
Here are 6 high-leverage hero tools that enable complex hiring workflows.
list_all_greenhouse_jobs
Retrieves a complete list of all job requisitions in your Greenhouse instance. This tool returns the job ID, name, requisition ID, active status, creation dates, departments, offices, hiring team members, and current openings.
Contextual usage: This is the foundational discovery tool. Claude uses this to map a human-readable job title to the specific internal job_id required for subsequent application or candidate lookups.
"Claude, pull a list of all open Engineering roles in the New York office, and tell me who the assigned hiring managers are."
list_all_greenhouse_candidates
Fetches candidate profiles across the ATS. Returns comprehensive candidate details including their ID, full name, current company, title, creation date, and heavily nested arrays detailing their educations, employments, applications, and custom fields.
Contextual usage: Claude can filter this list by specific tags or application dates to build lists of candidates for specific sourcing campaigns or pipeline reviews.
"Find all candidates added in the last 30 days who have 'Staff Engineer' in their current title, and summarize their previous employment history."
get_single_greenhouse_candidate_by_id
Retrieves detailed, isolated information about a specific candidate using their unique ID. This includes personal details, contact information, specific jobs they have applied for, and any associated tags.
Contextual usage: Used when Claude needs to deep-dive into a specific individual. It prevents the model from attempting to parse massive arrays when only one record is needed.
"Get the full profile for candidate ID 987654. What custom demographic fields were captured, and what tags are currently applied to their profile?"
list_all_greenhouse_applications
Lists all applications in the system. An application is the connective tissue between a candidate and a job. This tool returns the application ID, prospect status, applied date, source, credited recruiter, current stage, answers to application questions, and attachments (resumes/cover letters).
Contextual usage: Critical for tracking pipeline velocity. Claude uses this to determine exactly where candidates are stuck in the process.
"Show me all applications for the 'Senior Product Designer' role that are currently sitting in the 'On-site Interview' stage. Who is the credited recruiter for each?"
list_all_greenhouse_scheduled_interviews
Retrieves all scheduled interviews across the organization or for a specific application. It returns the interview ID, application ID, start and end times, location, video conferencing URLs, current status, organizer, and assigned interviewers.
Contextual usage: Allows Claude to act as a scheduling assistant, cross-referencing upcoming interviews to prepare daily briefing documents for hiring managers.
"List all interviews scheduled for tomorrow. Give me the start times, the video links, and the names of the interviewers involved."
list_all_greenhouse_scorecards
Extracts submitted feedback and scorecards. Returns the scorecard ID, the interview step it belongs to, the candidate ID, submission timestamps, the overall recommendation (e.g., 'Definitely Yes', 'No'), and the granular attributes, ratings, and notes submitted by the interviewer.
Contextual usage: Enables Claude to synthesize interview feedback automatically, turning hours of reading into concise candidate debrief summaries.
"Pull the latest scorecards for candidate ID 987654. Summarize the overall recommendations and highlight any concerns raised by the interviewers regarding their system design skills."
For a complete inventory of available Greenhouse endpoints and exact payload schemas, visit the Truto Greenhouse Integration Page.
Workflows in Action
When Claude has access to these tools, it stops being a simple chatbot and becomes an agentic recruiting assistant capable of multi-step reasoning. Because Truto flattens the input namespaces - allowing query parameters and body parameters to be routed seamlessly based on the generated schema - Claude can execute complex chained logic.
Workflow 1: The Hiring Manager Debrief Prep
Hiring managers often enter debrief meetings needing to synthesize feedback from 4-5 different interviewers. An AI agent can compile this instantly.
"I have a debrief meeting for the Staff DevOps Engineer role in an hour. Find the candidate named 'Sarah Jenkins', check what stage her application is in, and summarize all the scorecards submitted by the panel so far. Focus specifically on feedback regarding Kubernetes architecture."
Execution Trace:
list_all_greenhouse_candidates-> Claude searches forfirst_name: "Sarah"andlast_name: "Jenkins"to retrieve hercandidate_id.list_all_greenhouse_applications-> Claude filters by the retrievedcandidate_idto confirm she is applying for the DevOps role and checks hercurrent_stage.list_all_greenhouse_scorecards-> Claude queries scorecards attached to herapplication_id.- Synthesis: Claude parses the raw JSON ratings and notes, cross-references them against the user's prompt, and outputs a formatted Markdown summary detailing the consensus on her Kubernetes knowledge.
Workflow 2: Pipeline Velocity Audit
Talent Acquisition leaders need to ensure candidates aren't languishing in early stages for weeks at a time.
"Audit the 'Enterprise Account Executive' requisition. Find any applications that have been in the 'Initial Recruiter Screen' stage for more than 14 days without any scheduled interviews. List their names and the recruiter assigned to them."
Execution Trace:
list_all_greenhouse_jobs-> Claude searches for the "Enterprise Account Executive" title to grab the specificjob_id.list_all_greenhouse_applications-> Claude queries applications for thatjob_id, filtering forcurrent_stage: "Initial Recruiter Screen"and comparing thelast_activity_attimestamp against the current date.list_all_greenhouse_scheduled_interviews-> For any stalled applications, Claude checks if there is a pending calendar event.- Synthesis: Claude outputs a targeted list of neglected candidates, providing exactly what the TA leader needs to unblock the pipeline.
graph TD
A[User Prompt: Audit AE Pipeline] --> B[list_all_greenhouse_jobs]
B -->|Returns job_id: 84392| C[list_all_greenhouse_applications]
C -->|Filters stage & timestamp| D{Are interviews scheduled?}
D -->|Yes| E[Skip Candidate]
D -->|No| F[list_all_greenhouse_scheduled_interviews]
F --> G[Format Output Table]
G --> H[Return Markdown to User]Security and Access Control
Providing an LLM with access to sensitive ATS data requires rigid boundary setting. The Truto MCP server implementation includes specific safeguards applied at the protocol routing layer:
- Method Filtering: You can strictly configure an MCP token to only allow specific HTTP methods. Passing
config: { methods: ["read"] }during creation ensures that tools mapping tocreate,update, ordeleteoperations are completely stripped from the server's tool manifest. Claude literally cannot hallucinate a write command because the tool does not exist. - Tag Filtering: Integration resources are categorized by tags. If you want to limit Claude to only reading job descriptions and nothing about specific candidates, you can apply a tag filter (e.g.,
tags: ["jobs", "departments"]). Any endpoint lacking those tags is omitted. - Extra Authentication Layer: By default, possession of the cryptographic MCP URL grants access. For higher security environments, setting
require_api_token_auth: truemeans the client connecting to the MCP server must also pass a valid Truto API token in theAuthorizationheader, enforcing a dual-authentication layer. - Time-to-Live (TTL) Expiration: You can provision temporary access for external contractors or specific automation runs. Passing an
expires_atISO datetime ensures the server URL completely self-destructs via scheduled cleanup routines once the time expires, leaving no stale access vectors.
Moving Beyond Hardcoded Integrations
The gap between a standard LLM and an enterprise-grade AI agent is its ability to interact with external systems of record. Writing custom Python scripts to parse the Greenhouse Harvest API, handling the erratic pagination schemas, and managing OAuth lifecycles manually is a massive drain on engineering resources.
By utilizing a managed MCP server architecture, you abstract the connectivity layer entirely. Tools are dynamically derived from documentation, schemas are strictly enforced to prevent LLM hallucinations, and rate limits are handled transparently. This allows your team to focus entirely on prompt engineering and workflow orchestration, turning Claude into a fully integrated member of your Talent Acquisition team.
FAQ
- How does Truto handle Greenhouse API rate limits?
- Greenhouse strictly limits requests to 50 per 10 seconds. Truto does not retry, throttle, or apply backoff on rate limit errors. Instead, it passes the HTTP 429 error directly to Claude and normalizes the upstream rate limit information into standardized IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset). Your agent framework is responsible for handling the retry.
- Do I need to write custom JSON schemas for Greenhouse endpoints?
- No. Truto dynamically generates strict JSON schemas for every Greenhouse endpoint based on the integration's documentation and resources, converting them into standard MCP tools automatically.
- Can I restrict Claude to read-only access in Greenhouse?
- Yes. When generating the MCP server URL in Truto, you can configure method filtering to only allow read operations (like GET and LIST), preventing the LLM from creating or updating records.
- How does Claude handle Greenhouse's pagination?
- Greenhouse uses HTTP Link headers for pagination. Truto normalizes this by injecting standard limit and next_cursor parameters into the tool payload, instructing Claude to pass cursor values back unchanged to fetch subsequent pages.