Skip to main content
Glama
@kula-ai/mcp-server

@kula-ai/mcp-server

Official
by kula-ai

@kula-ai/mcp-server

CI npm License: MIT Node

An MCP (Model Context Protocol) server for the Kula recruiting API. Connect AI assistants like Claude to your Kula account to list jobs, manage applications, configure webhooks, and more.

Quick Start

With Claude Desktop

Add to your Claude Desktop configuration (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "kula": {
      "command": "npx",
      "args": ["-y", "@kula-ai/mcp-server"],
      "env": {
        "KULA_API_KEY": "your_api_key_here"
      }
    }
  }
}

Add to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "kula": {
      "command": "npx",
      "args": ["-y", "@kula-ai/mcp-server"],
      "env": {
        "KULA_API_KEY": "your_api_key_here"
      }
    }
  }
}
claude mcp add kula -- npx -y @kula-ai/mcp-server

Then set KULA_API_KEY in your environment.

Manual

npx @kula-ai/mcp-server

Related MCP server: Recruit CRM MCP

Configuration

Environment Variable

Required

Description

KULA_API_KEY

Yes

Your Kula API key

Get your API key from Kula Developer Settings.

Available Tools

51 tools across 13 categories:

Tool

Description

list_departments

List all departments in the organization as a nested tree structure

list_offices

List all offices in the organization

list_milestones

List all hiring milestones (pipeline stage groupings)

list_users

List all active internal users (recruiters, hiring managers, coordinators)

Tool

Description

list_sources

List all candidate sources in the organization

Tool

Description

list_rejection_reasons

List all rejection reasons configured in the organization

Tool

Description

list_custom_fields

List custom fields by subject type. Required — valid values: job, candidate, requisition, offer

Tool

Description

list_jobs

List jobs with filters (status, department, office, date ranges, sort)

search_jobs

Search jobs by title (partial match) with optional filters

get_job

Get details of a specific job

Tool

Description

list_job_stages

List all pipeline stages for a specific job

create_job_stage

Create a new pipeline stage for a job

list_stage_activities

List all activities configured for a specific job stage

Tool

Description

list_job_posts

List published job posts on the job board

get_job_post

Get details of a specific job post from the job board

Tool

Description

create_candidate

Create a new candidate in the system

list_candidates

List candidates with simple filters (email, date ranges, sort)

search_candidates

Search candidates by name, email, skills, tags, location, and more

get_candidate

Get details of a specific candidate

update_candidate

Update an existing candidate's profile

Tool

Description

list_applications

List job applications

get_application

Get details of a specific application

update_application_stage

Update the stage of a specific application

list_application_notes

List notes on a specific application

create_application_note

Add a note to a specific application

update_application_note

Update an existing note on an application

Tool

Description

list_scorecard_submissions

List scorecard submissions for a specific application

Tool

Description

list_webhooks

List all configured webhooks

create_webhook

Create a new webhook subscription

get_webhook

Get details of a specific webhook

update_webhook

Update an existing webhook configuration

delete_webhook

Delete a webhook

enable_webhook

Enable a disabled webhook

disable_webhook

Disable an active webhook

rotate_webhook_secret

Rotate the signing secret for a webhook

test_webhook

Send a test payload to a webhook endpoint

list_webhook_logs

List recent delivery logs for a webhook

list_webhook_events

List all available webhook event types

get_webhook_sample_payload

Get a sample webhook payload for a specific event type

Tool

Description

list_requisitions

List all requisitions for your account

get_requisition

Get detailed information about a specific requisition

list_requisition_fields

List default and custom field definitions for requisitions

create_requisition

Create a new requisition (supports linked groups via head_count)

update_requisition

Update an existing requisition

close_requisition

Close a requisition

Tool

Description

search_companies

Search companies by name

list_industries

List all available industries

search_locations

Search locations by query

search_institutions

Search academic institutions by name

search_disciplines

Search academic disciplines by name

list_degrees

List all available academic degrees

Development

# Use correct Node version
nvm use

# Install dependencies
npm install

# Build
npm run build

# Watch mode
npm run dev

# Run tests
npm test

# Test with MCP Inspector
npx @modelcontextprotocol/inspector node build/index.js

Connecting locally

To test your local build with an AI client instead of the published package:

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "kula": {
      "command": "node",
      "args": ["/absolute/path/to/kula-mcp/build/index.js"],
      "env": {
        "KULA_API_KEY": "your_api_key_here"
      }
    }
  }
}

Edit ~/.cursor/mcp.json:

{
  "mcpServers": {
    "kula": {
      "command": "node",
      "args": ["/absolute/path/to/kula-mcp/build/index.js"],
      "env": {
        "KULA_API_KEY": "your_api_key_here"
      }
    }
  }
}
claude mcp add kula -- node /absolute/path/to/kula-mcp/build/index.js

Then set KULA_API_KEY in your environment.

Note: The server uses STDIO transport, so there's no hot-reload. After rebuilding (npm run build or via npm run dev), restart the MCP client to pick up changes.

License

MIT

Available Tools

84 tools
cancel_interviewA

Cancel a scheduled interview. Calendar events are torn down and cancellation notifications dispatched asynchronously. Cannot cancel: already-cancelled interviews (err_interview_already_cancelled), or completed HackerRank interviews (err_cannot_cancel_completed_hackerrank).

Inputs: id (required).

check_interviewers_availabilityA

Compute free interview slots across the organizer + interviewers' calendars. Async — returns a poll_id immediately. Get the result two ways: (a) call get_interviewers_availability_result with the poll_id, or (b) subscribe to the interview.availability.computed webhook (recommended for production — avoids polling). Result expires 1 hour after computation.

Each returned slot carries interviewer_ids — the user IDs free at that range. For panel, every slot lists every interviewer in the request (a panel slot requires all of them to be free). For one_on_one, each slot lists the subset free at that range; pick one of those IDs when calling create_interview.

Inputs: organizer_id (required), interviewer_ids (required), start_time (required), duration_minutes (required), +3 more.

close_requisitionA

Close a requisition. Only requisitions in a closeable state can be closed.

Inputs: id (required), reason, apply_to_group.

create_application_noteB

Add a note to a specific application.

Inputs: application_id (required), body (required), notify_recruiter.

create_candidateA

Create a new candidate in Kula. At least one of email or linkedin_url (in social_urls) is required. Optionally link to a job pipeline via job_id and job_stage_id. Returns the created candidate object.

Inputs: first_name (required), last_name, email, phone_number, +9 more.

create_interviewA

Schedule an interview against an application. Calendar invites and conference URL are provisioned asynchronously — subscribe to the interview.event.created webhook to receive the fully-provisioned interview.

Typical workflow:

  1. Plan-driven: get_interview_plan → pick a stage_activity_id → check_interviewers_availability → create_interview with stage_activity_id (scorecard config inherits from the activity; pass scorecard_template_id only when stage_activity_id is NOT set).

  2. Ad-hoc: list_valid_organizers (organizer_id) → list_applications (application_id) → check_interviewers_availability → create_interview.

Where to discover IDs:

  • application_id → list_applications

  • organizer_id → list_valid_organizers (filtered by job_id)

  • interviewer_ids → list_users (any active user)

  • office_id → list_offices (required when location=onsite)

  • host_id → list_conference_hosts (required when location=zoom; must be in interviewer_ids)

  • stage_activity_id → get_interview_plan

  • interviewer_template_id / candidate_template_id → list_email_templates

  • scorecard_template_id → list_scorecard_templates

Constraints:

  • start_time must be on a 15-minute boundary with zero seconds (e.g. 09:00:00, 09:15:00) and in the future

  • duration_minutes must be a multiple of 15 (15..1440)

  • kind: one_on_one requires exactly one entry in interviewer_ids

Inputs: organizer_id (required), application_id (required), start_time (required), duration_minutes (required), +15 more.

create_job_stageB

Create a new pipeline stage for a job.

Inputs: job_id (required), name (required), milestone_id, position, +1 more.

create_requisitionA

Create a new requisition. When head_count exceeds 1, creates a group of linked requisitions. Use list_requisition_fields to get available custom field IDs for additional_info.

Inputs: role_name (required), employment_type (required), requisition_type (required), department_id (required), +13 more.

create_userA

Invite a new user to the account. The user is created in the pending state and sent an invitation email. Requires email and first_name.

Inputs: email (required), first_name (required), role_id, last_name, +5 more.

create_webhookB

Create a new webhook subscription.

Inputs: url (required), name (required), subscribed_events (required), secret, +2 more.

deactivate_userA

Deactivate a user. The user can no longer sign in but their historical activity is preserved.

Inputs: id (required).

delete_webhookB

Delete a webhook.

Inputs: id (required).

disable_webhookA

Disable an active webhook.

Inputs: id (required).

enable_webhookA

Enable a disabled webhook.

Inputs: id (required).

find_companiesB

Search the global company catalog. Returned IDs map to current_company_ids on candidate search.

Inputs: query (required), page, limit.

find_currenciesA

List currencies. Returned IDs map to salary_currency_id on requisitions.

Inputs: page, limit.

find_degreesB

List academic degrees, optionally filtered by name. Useful for discovering valid degree options for candidate education records.

Inputs: query, page, limit.

find_disciplinesB

Search academic disciplines (fields of study).

Inputs: query (required), page, limit.

find_industriesB

List industries used to classify companies. Paginated; useful for discovering valid industry options.

Inputs: page, limit.

find_institutionsB

Search academic institutions. Returned IDs map to institute_ids on candidate search.

Inputs: query (required), page, limit.

find_locationsA

Search cities, states, and countries. The returned type discriminator (city|state|country) tells you which places_*_id field on candidate endpoints the id maps to. City results also include state_id and country_id (parent chain); State results include country_id; Country results have both as null.

Inputs: query (required), page, limit.

find_skillsA

Search the global skill catalog. Returned IDs map to skill_ids on candidate search.

Inputs: query (required), page, limit.

find_tagsA

Search candidate tags (account-scoped). Returned IDs map to tag_ids on candidate search.

Inputs: query (required), page, limit.

get_applicationA

Get details of a specific application. Only use when the user asks about a specific application.

Inputs: id (required).

get_candidateA

Retrieve full details of a specific candidate by ID, including all applications, tags, skills, and location. Use this when you already have the candidate ID. To find a candidate by name or attributes, use search_candidates first.

Inputs: id (required).

get_email_templateA

Get full details for a single email or calendar-invite template, including subject, body, and owner.

Inputs: id (required).

get_interviewA

Get full details for a single interview, including interviewers, candidate, conference URL, scorecard refs.

Inputs: id (required).

get_interviewers_availability_resultA

Poll for the result of a previous check_interviewers_availability call. Returns 200 with status=succeeded/failed when terminated, 202 with status=pending while running, 410 if expired (1-hour TTL after completion). Respect the Retry-After header — don't poll faster than every 5s. For production loads, prefer the interview.availability.computed webhook.

Each slot in the response includes interviewer_ids — the user IDs free at that slot. Use one of those IDs as interviewer_ids (and host_id for zoom) when calling create_interview.

Inputs: poll_id (required).

get_interview_planA

Read the interview plan configured on a job — stages with their pre-configured interview activities. Each activity's id is the stage_activity_id to pass to create_interview (which inherits the activity's scorecard config).

Inputs: job_id (required).

get_jobA

Retrieve full details of a specific job by ID, including description and interview stages. Use this when you already have the job ID. To find a job by title, use search_jobs first.

Inputs: id (required).

get_job_postA

Get details of a specific job post from the job board. Only use when the user asks about a specific job board listing.

Inputs: id (required).

get_requisitionB

Get detailed information about a specific requisition, including description and custom field values.

Inputs: id (required).

get_roleA

Retrieve a single role by ID. Response includes a permissions object mapping resource:action keys (e.g. users:manage, jobs:read) to booleans indicating whether the role grants each one.

Inputs: id (required).

get_scorecard_templateA

Get full details for a single scorecard template — questions, feedback/rating descriptions, and segmentation.

Inputs: id (required).

get_userA

Retrieve a single user by ID. Response includes a permissions array of resource:action keys granted by the user's role.

Inputs: id (required).

get_webhookB

Get details of a specific webhook.

Inputs: id (required).

get_webhook_sample_payloadB

Get a sample webhook payload for a specific event type.

Inputs: event_type (required).

list_application_interviewsA

List the interviews scheduled on a specific application. Same as list_interviews but scoped to one application (the application_id goes in the path, not as a filter). Cancelled interviews are included by default — use meeting_status=cancelled etc. to filter.

Inputs: application_id (required), page, limit, interviewer_ids, +13 more.

list_application_notesC

List notes on a specific application.

Inputs: application_id (required), page, limit, sort_by, +5 more.

list_applicationsA

List job applications. Only use when the user explicitly asks about applications.

Inputs: page, limit, job_id, status, +8 more.

list_candidatesA

List candidates with simple filters: email, date ranges, and sorting. Use this for browsing or filtering by exact email. For full-text search or filtering by skills, tags, location, job pipeline, or resume presence — use search_candidates instead.

Inputs: page, limit, email, sort_by, +5 more.

list_conference_hostsA

List users eligible to be the conference host_id (e.g., for Zoom — they have an active workspace seat). Used when scheduling video-conference interviews.

Inputs: provider (required), query, page, limit.

list_custom_fieldsA

List custom fields configured in the organization. The type parameter is required — specify job, candidate, requisition, or offer.

Inputs: type (required), page, limit, sort_by, +7 more.

list_degreesB

List all available academic degrees.

Inputs: no named parameters.

list_departmentsA

List all departments as a flat paginated list. Each record has a parent_id to reconstruct the hierarchy client-side.

Inputs: page, limit, sort_by, sort_order, +4 more.

list_email_templatesA

List email and calendar-invite templates configured for the account. Per-interview snapshots and system templates are excluded. Use this to discover interviewer_template_id and candidate_template_id for create_interview.

Inputs: page, limit, query, channel, +8 more.

list_industriesB

List all available industries.

Inputs: no named parameters.

list_interviewsA

List interviews for the account. Supports rich multi-value filters: by job, application, candidate, interviewer, organizer, recruiter, department, office, status, kind, location, AI note-taker flag, and start_time window. Cancelled interviews are included by default — use meeting_status=cancelled etc. to filter.

Inputs: page, limit, job_ids, application_ids, +18 more.

list_job_postsA

List published job posts on the job board. Only use when the user explicitly asks about job board listings.

Inputs: page, limit, department_ids, office_ids.

list_jobsA

List jobs with SQL-based filters and sorting. Use this for browsing jobs or filtering by status, department, office, or date ranges. For title search (partial match supported), use search_jobs instead.

Inputs: page, limit, department_ids, office_ids, +7 more.

list_job_stagesC

List all pipeline stages for a specific job.

Inputs: job_id (required), page, limit, sort_by, +5 more.

list_milestonesB

List all hiring milestones (pipeline stage groupings) in the organization.

Inputs: page, limit, sort_by, sort_order, +4 more.

list_officesB

List all offices in the organization.

Inputs: page, limit, sort_by, sort_order, +4 more.

list_rejection_reasonsB

List all rejection reasons configured in the organization.

Inputs: page, limit, sort_by, sort_order, +6 more.

list_requisition_fieldsA

List default and custom field definitions for requisitions. Hidden fields are excluded. Optionally filter by department or office.

Inputs: department_ids, office_ids.

list_requisitionsC

List all requisitions for your account, respecting permissions.

Inputs: page, limit, status, department_ids, +18 more.

list_rolesA

List roles available in the account. Use this to discover valid role_id values for create_user and update_user.

Inputs: page, limit, sort_by, sort_order, +4 more.

list_scorecard_submissionsA

List scorecards for a specific application. Each scorecard may be linked to an interview, assessment, or review — use the type filter to narrow by activity type.

Inputs: application_id (required), status, type, page, +7 more.

list_scorecard_templatesA

List scorecard templates configured for the account. Use this to discover scorecard_template_id values to pass to create_interview (only honored when stage_activity_id is NOT set — interview-plan activities own scorecard config).

Inputs: page, limit, query, department_ids, +8 more.

list_sourcesB

List all candidate sources in the organization.

Inputs: page, limit, enabled, sort_by, +5 more.

list_stage_activitiesB

List all activities (actions) configured for a specific job stage.

Inputs: job_id (required), stage_id (required), page, limit, +6 more.

list_usersB

List users in the organization. Defaults to active users; use the status filter to include pending, deactivated, or imported. Supports filtering by role, department, office, granted permissions, and a full-text query across name and email.

Inputs: page, limit, sort_by, sort_order, +10 more.

list_valid_organizersA

List users eligible to be the organizer_id when scheduling an interview for a job — they have a connected calendar (Google or Microsoft) and permission to manage candidates on the job.

Inputs: job_id (required), query, page, limit.

list_webhook_eventsB

List all available webhook event types you can subscribe to.

Inputs: no named parameters.

list_webhook_logsA

List recent delivery logs for a webhook, including status and response details for each attempt.

Inputs: id (required), page, limit.

list_webhooksB

List all configured webhooks.

Inputs: page, limit.

mark_candidate_no_showA

Mark the candidate as a no-show on an in_progress or ended interview. Cannot be marked when a scorecard has been submitted.

Inputs: id (required).

reactivate_userC

Reactivate a previously deactivated user.

Inputs: id (required).

rotate_webhook_secretB

Rotate the signing secret for a webhook.

Inputs: id (required).

search_candidatesA

Search candidates using Elasticsearch with rich filters and cursor-based pagination. Preferred over list_candidates when you need: full-text search (name, email, resume), filtering by skills, tags, sources, job pipeline, location, or resume presence. Pagination: pass cursor from the previous response meta.next_cursor to get the next page. IMPORTANT: if you change any filter or search parameter, omit cursor and start a new request — cursors are tied to a specific search context and will return wrong results if filters change.

Inputs: cursor, query, skill_ids, tag_ids, +13 more.

search_companiesB

Search companies by name. Useful for autocompleting company names.

Inputs: query (required).

search_disciplinesA

Search academic disciplines by name. Useful for autocompleting field of study.

Inputs: query (required).

search_institutionsA

Search academic institutions by name. Useful for autocompleting university or school names.

Inputs: query (required).

search_jobsA

Search jobs by title (partial match supported) with optional filters. Preferred over list_jobs when you need to find jobs by name. Results are sorted by relevance.

Inputs: query, department_ids, office_ids, status, +8 more.

search_locationsA

Search locations by query. Useful for autocompleting city or region names.

Inputs: query (required).

test_webhookA

Send a test payload to a webhook and wait for the delivery result. Polls until delivered or failed (30s timeout).

Inputs: id (required).

undo_candidate_no_showA

Reverse a candidate no-show. Allowed only when meeting_status is candidate_no_show.

Inputs: id (required).

update_application_noteB

Update an existing note on an application.

Inputs: application_id (required), id (required), body, notify_recruiter.

update_application_stageC

Update the stage of a specific application.

Inputs: id (required), stage_id (required), requisition_code.

update_candidateA

Update an existing candidate's profile. All fields are optional — only send the fields you want to change. Returns the updated candidate object.

Inputs: id (required), first_name, last_name, email, +8 more.

update_interviewA

Update an existing interview. All fields are optional — only the supplied fields are modified. Immutable fields (cannot be changed after creation): organizer_id, application_id, job_id, stage_id, candidate_id, stage_activity_id, scorecard_template_id. Cancelled interviews cannot be updated (returns 422 err_interview_cancelled).

Inputs: id (required), start_time, duration_minutes, timezone, +12 more.

update_requisitionA

Update an existing requisition. Cannot modify requisitions with closed, archived, or filled statuses. Pass all custom field values in additional_info — omitted fields will be cleared.

Inputs: id (required), role_name, employment_type, requisition_type, +15 more.

update_userA

Update an existing user. Only supplied fields are modified. Email and account status cannot be changed via this endpoint.

Inputs: id (required), first_name, last_name, job_title, +5 more.

update_webhookA

Update an existing webhook configuration. Only include fields you want to change.

Inputs: id (required), url, name, subscribed_events, +2 more.

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 84 tools

    Disambiguation5/5

    Each tool has a distinct, purpose-specific name and detailed description that clearly differentiates it from others. There is no overlap; even similar operations like 'list_candidates' vs 'search_candidates' are explained with different use cases.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun snake_case pattern (e.g., cancel_interview, create_candidate, get_job). No mixing of casing or irregular naming is observed.

    Tool Count1/5

    84 tools is extremely high for an MCP server, far exceeding the typical 3-15 range. While the domain is broad, this count is excessive and likely to overwhelm agents and reduce coherence.

    Completeness5/5

    The tool set covers the full lifecycle of recruiting: candidates, applications, interviews, jobs, requisitions, users, webhooks, and reference data (skills, locations, etc.). CRUD operations are present for core entities, with additional utilities like searching and webhook management. No obvious gaps are apparent.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      This MCP server provides hiring automation tools for recruitment processes. It enables users to generate job descriptions, score CVs, create interview questions, benchmark salaries, and draft offer letters through natural language interactions.
      16 npm
      31 PyPI
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      MCP server for Recruit CRM, enabling AI assistants to search candidates, view jobs, and manage recruiting workflows.
      53
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      MCP server connecting AI assistants to official France Travail APIs for real-time job offers, ROME code prediction, and hiring company search.
      7
      80 npm
      1
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      MCP server for Hunaras, an AI-native recruiting platform that enables candidates and employers to manage jobs, applications, assessments, and talent sourcing through natural language.
      14 npm
      MIT