Skip to main content
Glama
ashby-mcp

ashby-mcp

by dewierwan

ashby-mcp

MCP server for Ashby ATS — designed for candidate evaluation workflows.

This server exposes Ashby's recruiting data through the Model Context Protocol, letting AI agents review candidates, read application details, and write evaluation notes.

Prerequisites

You need an Ashby API key:

  1. Go to your Ashby admin settings → Integrations → API Keys

  2. Create a new API key with these permissions:

    • candidatesRead — read candidate profiles, applications, notes, feedback

    • jobsRead — read job listings and details

    • interviewsRead — read interview stages and plans

    • candidatesWrite — add notes, tags, move application stages, archive applications

    • hiringProcessMetadataRead — list archive reasons and email templates

Optional permissions for the raw API tool:

  • apiKeysRead — inspect the current key with apiKey.info.

  • sourcingRead — read sequence templates, email senders, and existing sequences.

  • emailsRead — read recent candidate email messages.

A 403 with missing_endpoint_permission requires updating the key's permissions in Ashby Admin > Integrations > API Keys. The MCP reports the endpoint and required permission for these operations. Email and sequence endpoints may also require beta access for your organization; see the Ashby authentication reference and the endpoint's documentation.

Related MCP server: MCP Ashby Connector

Install

Run in your terminal:

claude mcp add ashby -e ASHBY_API_KEY=your-api-key-here -- npx -y ashby-mcp@latest

This auto-updates whenever a new version is published.

Claude Desktop

Add this to your Claude Desktop MCP config (Settings → Developer → Edit Config):

{
  "mcpServers": {
    "ashby": {
      "command": "npx",
      "args": ["-y", "ashby-mcp@latest"],
      "env": {
        "ASHBY_API_KEY": "your-api-key-here"
      }
    }
  }
}

This also auto-updates on each restart.

Alternative: You can download the .mcpb bundle and double-click to install — no terminal needed. Note that this method pins you to a specific version and won't auto-update. You'll need to re-download after each release.

Other MCP clients

Add the same JSON config above to your client's MCP server configuration.

Docker

Build the image, then add it to your MCP client config:

docker build -t ashby-mcp .
{
  "mcpServers": {
    "ashby": {
      "command": "docker",
      "args": ["run", "--rm", "-i", "-e", "ASHBY_API_KEY", "ashby-mcp"],
      "env": {
        "ASHBY_API_KEY": "your-api-key-here"
      }
    }
  }
}

From source

git clone https://github.com/dewierwan/ashby-mcp.git && cd ashby-mcp
npm install
npm run build

Then point your MCP client at node dist/index.js with the ASHBY_API_KEY environment variable set.

Tools

All tools return dual-format responses: a human-readable summary followed by structured JSON.

Jobs

ashby_list_jobs

List open jobs with IDs, titles, department, location, and status.

Parameter

Type

Default

Description

status

"Open" | "Closed" | "Archived" | "Draft" | "All"

"Open"

Filter by job status

limit

number (1-100)

25

Max results per page

cursor

string

—

Pagination cursor from previous response

ashby_get_job_details

Full job details including description and interview plan stages.

Parameter

Type

Required

Description

job_id

string

Yes

Job ID (UUID)

ashby_get_pipeline_summary

Pipeline overview with candidate counts per stage, per job.

Parameter

Type

Default

Description

job_id

string

—

Summary for one job. Omit for all jobs.

status

"Open" | "Closed" | "All"

"Open"

Which jobs to include

Candidates

ashby_get_candidate

Comprehensive candidate profile with all applications resolved.

Parameter

Type

Required

Description

candidate_id

string

Yes

Candidate ID (UUID)

ashby_get_candidate_notes

All notes on a candidate.

Parameter

Type

Required

Description

candidate_id

string

Yes

Candidate ID (UUID)

ashby_search_candidates

Search candidates by name or email.

Parameter

Type

Default

Description

query

string

—

Candidate name to search for (required)

email

string

—

Optional email (AND logic with name)

limit

number (1-100)

25

Max results

ashby_add_candidate_note

Add an evaluation note to a candidate. Visible to the hiring team.

Parameter

Type

Required

Description

candidate_id

string

Yes

Candidate ID (UUID)

note

string

Yes

Note content (plain text)

ashby_add_candidate_tag

Tag a candidate (e.g. "Strong Hire", "Needs Review").

Parameter

Type

Required

Description

candidate_id

string

Yes

Candidate ID (UUID)

tag_id

string

Yes

Tag ID (UUID) from Ashby admin settings

ashby_get_resume

Download and extract text from a candidate's resume (PDF, text).

Parameter

Type

Required

Description

file_handle

string

Yes

File handle from candidate's fileHandles array

file_name

string

No

Original filename (helps determine format)

Applications

ashby_list_candidates_for_job

List candidates/applications for a specific job with stage and status.

Parameter

Type

Default

Description

job_id

string

—

Job ID (UUID) (required)

limit

number (1-100)

25

Max results per page

cursor

string

—

Pagination cursor

ashby_get_application_details

Full application with stage history, feedback, and criteria evaluations.

Parameter

Type

Required

Description

application_id

string

Yes

Application ID (UUID)

ashby_get_application_form_submission

Candidate's submitted application form responses (screening questions, cover letter, etc).

Parameter

Type

Required

Description

application_id

string

Yes

Application ID (UUID)

ashby_list_applications

List applications across all jobs with date, status, stage, and source filters.

Parameter

Type

Default

Description

created_after

string (ISO datetime)

—

Only applications after this time

created_before

string (ISO datetime)

—

Only applications before this time

job_id

string

—

Filter to a specific job

status

"Active" | "Archived" | "Hired" | "Lead" | "All"

"All"

Filter by status

stage_type

"Lead" | "PreInterviewScreen" | "Interview" | "Offer" | "All"

—

Filter by stage type

stage_name

string

—

Filter by exact stage name

source

string

—

Filter by source (case-insensitive substring)

limit

number (1-100)

25

Max results

cursor

string

—

Pagination cursor

ashby_archive_application

Archive an application with reason and optional rejection email.

Parameter

Type

Default

Description

application_id

string

—

Application ID (UUID) (required)

archive_reason_id

string

—

Reason ID from ashby_list_archive_reasons

send_email

boolean

false

Send rejection email (requires email_template_id)

email_template_id

string

—

Template ID from ashby_list_email_templates

ashby_bulk_archive

Archive multiple applications at once (max 25).

Parameter

Type

Default

Description

application_ids

string[] (1-25)

—

Application IDs (required)

archive_reason_id

string

—

Reason ID, applied to all

send_email

boolean

false

Send rejection emails

email_template_id

string

—

Template ID for rejection emails

ashby_archive_by_filter

Find and archive every application matching a set of filters in one call. It pages through application.list itself, so you don't need to collect IDs first. Use it for bulk cleanups instead of ashby_bulk_archive.

Filters combine with AND. At least one filter is required, so the tool can never run unfiltered.

Parameter

Type

Default

Description

job_ids

string[]

—

Only these jobs

job_status

("Open" | "Closed" | "Archived" | "Draft")[]

—

Only jobs with these statuses

job_closed_before

string (ISO date)

—

Only jobs whose updatedAt is before this date. Ashby has no closed-at field, so updatedAt is the proxy; a later edit to a job makes it look more recently closed. Without job_status, only Closed and Archived jobs are considered.

application_status

("Active" | "Lead")[]

—

Only applications with these statuses

stage_titles

string[]

—

Only applications whose current stage title matches (case-insensitive)

created_before

string (ISO date)

—

Only applications created before this date

exclude_candidate_ids

string[]

—

Keep-list: never archive these candidates' applications

exclude_application_ids

string[]

—

Keep-list: never archive these applications

archive_reason_id

string

—

Reason ID. Required when dry_run is false.

send_email

boolean

false

Send rejection emails (requires email_template_id)

email_template_id

string

—

Template ID for rejection emails

dry_run

boolean

true

Report what would be archived without changing anything

max_applications

number

500

Safety cap. A real run refuses if more would be archived.

Hired and already-archived applications are never touched. Archives run five at a time, with extra backoff on 429 and 5xx responses. One failure never stops the run.

The response is compact: totals (matched, to archive, archived, skipped by reason, failed), a per-job breakdown, up to 10 sample names per job in a dry run, and every failure with its error. It does not list archived IDs.

Safe workflow: always run with dry_run: true first (the default). Check the totals, per-job counts and sample names, then repeat the same call with dry_run: false.

Dry run: preview every lead on jobs closed before 4 July 2026.

{
  "job_closed_before": "2026-07-04",
  "application_status": ["Lead"]
}

Real run: archive them, keeping two candidates and allowing up to 1,500 archives.

{
  "job_closed_before": "2026-07-04",
  "application_status": ["Lead"],
  "exclude_candidate_ids": ["<candidate-uuid>", "<candidate-uuid>"],
  "archive_reason_id": "<reason-uuid>",
  "dry_run": false,
  "max_applications": 1500
}

Interviews

ashby_list_interview_stages

List all interview stages across all interview plans. No parameters.

ashby_list_upcoming_interviews

List upcoming and pending interview schedules.

Parameter

Type

Default

Description

start_after

string (ISO datetime)

now

Only interviews after this time

start_before

string (ISO datetime)

—

Only interviews before this time

status

"Scheduled" | "NeedsScheduling" | "Complete" | "Cancelled" | "All"

"All"

Filter by status

limit

number (1-100)

25

Max results

Workflow

ashby_move_application_stage

Move an application to a different interview stage.

Parameter

Type

Required

Description

application_id

string

Yes

Application ID (UUID)

stage_id

string

Yes

Target stage ID from ashby_list_interview_stages

ashby_get_feedback

Submitted feedback/scorecards for an application.

Parameter

Type

Required

Description

application_id

string

Yes

Application ID (UUID)

ashby_list_archive_reasons

List available archive/rejection reasons. No parameters.

ashby_list_email_templates

List email templates for rejection emails. No parameters.

Escape hatch

For anything the dedicated tools above don't cover (e.g. offer.list, user.list, department.list, interviewPlan.list, candidate.update), use the two generic tools below. They share the same auth, retries, and timeouts as every other tool.

ashby_call_api

Call any Ashby API endpoint directly. Returns the raw response envelope, including success, results, moreDataAvailable, and error details.

Parameter

Type

Required

Description

endpoint

string

Yes

Endpoint path, e.g. "offer.list", "user.list", "candidate.update". No leading slash.

params

object

No

JSON body to POST. Defaults to {}.

Marked destructiveHint: true so Claude surfaces the call before running it (a generic passthrough can hit write endpoints).

ashby_get_api_docs

Return a curated reference for the Ashby API: base URL, auth, response envelope, pagination, endpoint index grouped by resource, and common gotchas. No parameters.

Call this before ashby_call_api if you're not sure which endpoint or parameter names to use. Full official reference: https://developers.ashbyhq.com/reference/.

Example Prompts

Show me all open engineering jobs.

List the candidates for the Senior Backend Engineer role and summarize where each one is in the pipeline.

Pull up the full profile for candidate Jane Smith — I want to see her resume info, application history, and any existing notes.

Review the feedback submitted for application abc-123 and summarize the interviewer evaluations.

Add a note to candidate xyz-456: "Strong technical skills demonstrated in system design round. Recommend advancing to final interview."

Move application abc-123 to the "Final Interview" stage.

Read the resume for candidate Jane Smith and summarize her experience.

How many people applied this week?

What does our pipeline look like for the Community Lead role?

Show me all candidates currently in the Work test stage.

Archive John Smith's application for the Senior Engineer role with reason "Not enough experience" and send the standard rejection email.

Show me the available archive reasons and rejection email templates.

Bulk archive all candidates in Application Review for the closed Designer role.

Dry-run archiving every lead on jobs closed before July, then archive them.

Privacy

  • This server proxies requests to the Ashby API using your own API key.

  • No data is stored, logged, or sent anywhere other than Ashby's API endpoints (api.ashbyhq.com).

  • Your API key is stored locally on your machine and is never transmitted to any third party.

Testing

Verify API connectivity

ASHBY_API_KEY=your-key npm run test-api

Test with MCP Inspector

ASHBY_API_KEY=your-key npx @modelcontextprotocol/inspector node dist/index.js

Run directly

ASHBY_API_KEY=your-key node dist/index.js

The server communicates over stdio — it will start silently and wait for MCP protocol messages.

Development

npm install
npm run build    # compile TypeScript to dist/
npm test         # run tests
npm start        # run the built server

Available Tools

24 tools
ashby_add_candidate_noteA

Add an evaluation note to a candidate.

Use this to record your assessment or recommendations. The note will be visible to the hiring team in Ashby.

Response: note_id, confirmation message.

Inputs: note (required), candidate_id (required).

ashby_add_candidate_tagA
Idempotent

Tag a candidate with a label (e.g. "Strong Hire", "Needs Review").

Use this to categorize candidates during evaluation. You need the tag ID from Ashby admin settings.

Response: confirmation message.

Inputs: tag_id (required), candidate_id (required).

ashby_add_leadA

Create a new candidate and add them as a lead on a job.

Use this to source candidates (e.g. from LinkedIn) directly into Ashby. Creates the candidate, adds a Lead application on the specified job, and optionally attaches a note with sourcing context.

Response: candidate_id, application_id, note_id (if note provided), confirmation message.

Inputs: name (required), job_id (required), note, email, +2 more.

ashby_archive_applicationA
Destructive

Archive an application with an optional reason and rejection email.

Workflow: call ashby_list_archive_reasons to pick a reason, then ashby_list_email_templates to pick an email template, then call this tool. Automatically resolves the correct "Archived" interview stage for the application's job.

Response: application_id, status, archive_reason_id, email_sent, message.

Inputs: application_id (required), send_email, archive_reason_id, email_template_id.

ashby_bulk_archiveA
Destructive

Archive multiple applications at once with an optional reason and rejection email.

Accepts up to 25 application IDs. Uses the same archiving logic as ashby_archive_application for each one. Caches interview plan lookups for efficiency when applications share the same job.

Response: total, succeeded, failed, results[] (application_id, success, error?).

Inputs: application_ids (required), send_email, archive_reason_id, email_template_id.

ashby_call_apiA
Destructive

Call any Ashby API endpoint directly. Escape hatch for endpoints the narrow ashby_* tools don't wrap (e.g. offer.list, user.list, department.list, interviewPlan.list, candidate.update).

Prefer the dedicated tool when one exists — they return cleaner, summarised data. Use this when you need an endpoint that has no dedicated tool.

Call ashby_get_api_docs first if you're not sure which endpoint to use.

Handles auth, retries, and timeouts automatically. Returns the raw Ashby response including success, results, moreDataAvailable, nextCursor, and any error details — nothing is stripped.

Inputs: endpoint (required), params.

ashby_get_api_docsA
Read-only

Return a reference for the Ashby API: base URL, auth, response envelope, pagination, and a curated endpoint index with parameter hints and common gotchas.

Call this before ashby_call_api when you're unsure which endpoint or param names to use. The full official reference is at https://developers.ashbyhq.com/reference/.

Inputs: no named parameters.

ashby_get_application_detailsA
Read-only

Get full application details including stage history, hiring team, feedback, and criteria evaluations.

Use this to deep-dive into a specific application. Fires four API calls concurrently for speed.

Response: application (id, status, candidate, job, current_stage, hiringTeam, source, customFields), stage_history[], criteria_evaluations[], feedback[].

Inputs: application_id (required).

ashby_get_application_form_submissionA
Read-only

Get a candidate's submitted application form responses for a specific application.

Use this to read what a candidate actually wrote in their application — their answers to screening questions, cover letter text, and any other form fields. Use after ashby_list_candidates_for_job or ashby_get_application_details when you need to evaluate a candidate's application content.

Response: application_id, candidate_name, job_title, form_responses[] (question, field_type, answer).

Inputs: application_id (required).

ashby_get_candidateA
Read-only

Get a comprehensive candidate profile.

Returns everything needed to evaluate a candidate: name, contact info, social links, tags, resume/file handles, source, and all their applications with current stages. Fetches the candidate profile, then resolves each application for full details.

Response: candidate (id, name, email, phone, socialLinks, tags, source, profileUrl, fileHandles), applications[] (id, status, job, current_stage, source, hiringTeam).

Inputs: candidate_id (required).

ashby_get_candidate_notesA
Read-only

List all notes on a candidate.

Use this to see existing evaluation notes or comments left by the hiring team.

Response: notes[] (id, content, createdAt, author).

Inputs: candidate_id (required).

ashby_get_feedbackA
Read-only

Get submitted feedback/scorecards for an application.

Use this to review interviewer evaluations and scores.

Response: feedback[] (form definition with sections/fields, submitted values).

Inputs: application_id (required).

ashby_get_job_detailsA
Read-only

Get full details for a specific job including its description and interview plan stages.

Use this after ashby_list_jobs to understand a position's requirements and hiring pipeline. Fetches the job, resolves the job posting description, and interview plan stages automatically.

Response: job (id, title, status, description, hiringTeam, customFields, locationId, departmentId), interview_stages[] (id, title, type, order).

Inputs: job_id (required).

ashby_get_pipeline_summaryA
Read-only

Get a pipeline summary showing candidate counts per interview stage, per job.

Use this to answer "What does our pipeline look like?", "How many candidates at each stage?", or "Give me an overview of where things stand across open roles." The MCP server fetches and aggregates all applications internally — no need to paginate manually.

Response: jobs[] (job_id, job_title, total_active, total_archived, stages[] (stage_title, stage_type, count)), totals (active, archived, leads).

Inputs: job_id, status.

ashby_get_resumeA
Read-only

Download and read a candidate's resume or uploaded file.

Use this after ashby_get_candidate to read the actual content of a resume or file. Takes a file handle string from the candidate's fileHandles array. Fetches the file URL from Ashby, downloads the file, and returns the text content.

Supports PDF, DOCX (as plain text), and plain text files. For other formats, returns the download URL.

Response: filename, content (extracted text), or url (for unsupported formats).

Inputs: file_handle (required), file_name.

ashby_list_applicationsA
Read-only

List applications across all jobs with date, status, stage, and source filters.

Use this to answer operational questions like "How many people applied this week?", "Show me all candidates in Application Review", or "Who applied via the Chrome extension?" Date and status filtering happens server-side for efficiency. Stage and source filters are applied by the MCP server.

Response: items[] (application_id, candidate_id, candidate_name, candidate_email, status, current_stage, source, job_id, job_title, createdAt), has_more, next_cursor.

Inputs: limit, cursor, job_id, source, +5 more.

ashby_list_archive_reasonsA
Read-only

List available archive/rejection reasons.

Use this as the first step when archiving a candidate. Returns reasons you can pass to ashby_archive_application. Requires the "hiringProcessMetadataRead" API key permission.

Response: reasons[] (id, text, reasonType).

Inputs: no named parameters.

ashby_list_candidates_for_jobA
Read-only

List all candidates/applications for a specific job.

Returns each application with the candidate's name, current interview stage, and status. Use this to see the pipeline for a job. Pass next_cursor to paginate.

Response: items[] (application_id, candidate_id, candidate_name, status, current_stage, source, createdAt), has_more, next_cursor.

Inputs: job_id (required), limit, cursor.

ashby_list_email_templatesA
Read-only

List available email templates for rejection/archive emails.

Use this to find the template ID to pass to ashby_archive_application when sending a rejection email. Requires the "hiringProcessMetadataRead" API key permission.

Response: templates[] (id, name, and any other fields returned by the API).

Inputs: no named parameters.

ashby_list_interview_stagesA
Read-only

List all interview stages across all interview plans.

Use this to understand the hiring pipeline and get stage IDs for ashby_move_application_stage. Fetches all interview plans, then resolves stages for each.

Response: plans[] (plan_id, plan_title, stages[] (id, title, type, order)).

Inputs: no named parameters.

ashby_list_jobsA
Read-only

List jobs from Ashby with their IDs, titles, department, location, and status.

Use this to discover what positions exist before looking at candidates. Returns a paginated list — pass the next_cursor value to fetch more results.

Response: items[] (id, title, status, locationId, departmentId), has_more, next_cursor.

Inputs: limit, cursor, status.

ashby_list_upcoming_interviewsA
Read-only

List upcoming and pending interview schedules.

Use this to answer "What interviews do I have this week?", "Who needs to be scheduled?", or "Show me all upcoming interviews." Fetches interview schedules from Ashby, resolves candidate and job details, and filters by date range.

Response: items[] (schedule_id, status, candidate_name, candidate_id, job_title, job_id, interview_stage, events[] (start_time, end_time, interviewers, meeting_link, location, has_submitted_feedback)).

Inputs: limit, status, start_after, start_before.

ashby_move_application_stageA
Destructive

Move an application to a different interview stage.

Use this to advance a candidate through the pipeline. Get stage IDs from ashby_list_interview_stages. Moving to an "Archived" type stage requires an archive reason — use only for active transitions.

Response: updated application with new current_stage.

Inputs: stage_id (required), application_id (required).

ashby_search_candidatesA
Read-only

Search for candidates by name or email.

Use this when you know a candidate's name or email but not their ID. Both name and email use AND logic if both provided. Max 100 results.

Response: candidates[] (id, name, email, phone).

Inputs: query (required), email, limit.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4/5.0

    Scored across 24 tools

    Disambiguation4/5

    Most tools have clear boundaries: jobs, candidates, applications, interviews, archive reasons, and API docs are separated by verb and object. Some overlap exists (get_application_details includes feedback, making get_feedback partly redundant; list_applications and list_candidates_for_job both return pipeline lists), but descriptions usually steer the agent to the right tool.

    Naming Consistency4/5

    The set consistently uses ashby_ + snake_case + verb_noun naming (list_jobs, get_candidate, move_application_stage). Minor deviations like bulk_archive (missing its object) and the generic call_api/get_api_docs pair keep it from being a perfect 5.

    Tool Count3/5

    24 tools is at the heavy end of the 16-25 range. The breadth is understandable for an ATS, but the count is inflated by near-duplicates (archive_application vs bulk_archive, get_feedback vs get_application_details) and two meta-tools, so the set could be tightened.

    Completeness4/5

    Core recruiting workflows are covered: listing jobs, sourcing candidates, reading resumes/notes/form responses, moving stages, archiving, and reviewing feedback. Missing pieces like candidate updates, offer management, and interview scheduling are left to ashby_call_api, which prevents hard dead ends though it pushes work onto the agent.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers