# JOIN MCP connector

Connect JOIN once in Elaichi and Claude, ChatGPT, Cursor, or any MCP client can read and update JOIN jobs, applications, candidates, notes, and offices as the signed-in recruiter, with every action logged.

Source: https://elaichi.ai/connectors/join/

## Facts

| | |
| --- | --- |
| Application | JOIN |
| Category | ATS |
| AI tools | 30 |
| Authentication | Connects with an API key |
| Bring your own OAuth app | No |
| MCP endpoint | https://api.elaichi.ai/mcp |
| Works with | Claude, ChatGPT, Cursor, any MCP client, and the Elaichi Agent |
| Tools advertised by name | No. Connected tools are never listed one by one, however few there are. The endpoint advertises `search_tools` and `execute_tool` instead |

## What you can ask once JOIN is connected

- List open JOIN jobs with the number of applications on each.
- Add a note to Maria Lopez's candidate record about today's screening call.
- Archive every job in the Berlin office that was filled last month.

## Connect JOIN in Elaichi

This happens once for the organization, before any client is involved.

1. Open Connections, choose Add connection, and pick JOIN.
2. Optionally set Share with, then press Connect.
3. Paste a JOIN API key. One person generates a token in JOIN and pastes it once. Everyone else works through Share with, and never sees it.

Credentials are vaulted and nobody, including the AI, reads them back. The connection becomes a toolbox immediately, so you can curate which JOIN tools are exposed, rename them, or freeze arguments before anyone points a client at it.

## JOIN MCP connector for Claude

Endpoint: https://api.elaichi.ai/mcp

1. Open Customize, then Connectors.
2. Press Add.
3. Name it, paste the MCP server URL, then Continue.
4. Sign in and approve.

On Team and Enterprise, an Owner adds it once. Everyone else turns it on for themselves.

## JOIN MCP connector for ChatGPT

Endpoint: https://api.elaichi.ai/mcp

1. Open Plugins, then press the + button.
2. Name it and paste the endpoint into Server URL.
3. Leave Authentication on OAuth, then tick the risk acknowledgement.
4. Press Create, then sign in and approve.

Works on the web today. The plugin directory lives at chatgpt.com/plugins.

## JOIN MCP connector for Cursor

Endpoint: https://api.elaichi.ai/mcp

1. Open `~/.cursor/mcp.json`.
2. Add the endpoint under `mcpServers`.
3. Reload Cursor, then sign in and approve.

Set up per machine, so repeat it on each computer you work from.

## Connect JOIN to any MCP client

Endpoint: https://api.elaichi.ai/mcp

1. Add the endpoint as a remote MCP server.
2. Sign in and approve.

The Elaichi Agent already has these tools, with nothing to set up.

## What the consent screen decides

Only Read is granted by default, which is not enough to call a JOIN tool. Over MCP there is no trusted place to confirm a write in the moment, so the consent screen is the standing approval rather than a formality. Grant Read and Run tools. Think hard before granting Delete, which reaches into connected apps and cannot be undone.

## What teams do with JOIN through Elaichi

### Catch a candidate up after a screening call

Recruiting. Pull up the candidate in JOIN, add a note with what you heard, and move their application to the next stage without leaving the conversation.

### See every open job and who applied

Hiring managers. Ask for the open jobs in JOIN, then the applications on one role, and get a plain summary of where each applicant stands.

### Draft a new job in JOIN from a brief

HR. Turn a short brief into a JOIN job, review the wording, and activate it when the hiring manager signs off.

### Archive filled roles in one pass

Talent acquisition. Change the status of every job that was filled this month and archive them together, so the live list in JOIN only shows what is still open.

### Move a batch of applications at once

Recruiting operations. After an interview day, update a whole set of JOIN applications in one go and attach reference numbers from your HR system to each.

### Keep office locations accurate

People Ops. Add a new office in JOIN when a site opens and correct an address or name when something changes, so every job posts against the right location.

## Elaichi vs Zapier MCP vs Composio for JOIN

All three can connect JOIN to an AI assistant, and all three have admin controls. They differ in where access lives and how you pay.

| What to check | Elaichi | Zapier MCP | Composio |
| --- | --- | --- | --- |
| Where the AI connects | One address for the whole organization. Endpoint: https://api.elaichi.ai/mcp | A server per member, created at sign-in. | An MCP endpoint per team, or an SDK. |
| Control over JOIN tools | Allow or restrict single JOIN tools, per role or user. | App and action restrictions on the account. | Role permissions, down to the action. |
| Record of calls | One audit entry per JOIN call. | A History tab of tool calls. | A log of every tool call. |
| Single sign-on | SAML or OIDC, plus SCIM, on Gold. | SAML on Enterprise. | SAML and OIDC on Enterprise. |
| Price | $15 per user per month. | 2 tasks per successful call. | Billed per tool call. |

Sources: Zapier MCP [docs](https://docs.zapier.com/mcp/get-started/quickstart), [security](https://docs.zapier.com/mcp/manage/security), [usage](https://docs.zapier.com/mcp/features/usage); Composio [docs](https://docs.composio.dev/docs/composio-connect), [gateway](https://composio.dev/mcp-gateway), [enterprise](https://composio.dev/enterprise), [pricing](https://composio.dev/pricing). Checked September 2026.

Longer take: [Zapier MCP alternative](/blog/zapier-mcp-alternative/) and [when you don't need an MCP gateway](/blog/when-you-dont-need-an-mcp-gateway/).

## Frequently asked questions

### How do I connect JOIN to Claude?

First connect JOIN in Elaichi by pasting the API key from your JOIN account; there is no OAuth application to register and no client ID or secret to generate. Then open Claude, go to Customize, then Connectors, then Add, and paste https://api.elaichi.ai/mcp. Sign in as yourself and JOIN jobs, candidates, and applications are available in Claude.

### Does JOIN work with ChatGPT and Cursor as well as Claude?

Yes. JOIN is connected once in Elaichi, and the same endpoint, https://api.elaichi.ai/mcp, works in Claude, ChatGPT, Cursor, any other MCP client, and the Elaichi Agent. You do not set JOIN up again for each client.

### What can an AI agent actually do with my JOIN data?

With JOIN connected, an agent can list open jobs, look up a candidate, read the applications on a role, add or update notes, change application stages, create and activate jobs, archive filled ones, and keep office locations current. Short, concrete asks work best, such as "show me the applications on the Berlin sales job" rather than a long paragraph.

### Does connecting JOIN give the AI access to everything in my JOIN account?

No. Every call to JOIN runs inside the access of the person who signed in, so the agent sees the jobs, candidates, and applications that person can already see in JOIN. Elaichi can narrow that further with roles and restrictions, and it can never widen it.

### Can my team share one JOIN connection?

Yes. One person connects JOIN in Elaichi and shares the connection with a team, and nobody else ever handles the JOIN API key. Each teammate still signs in to Elaichi as themselves, so the audit log names the person behind every change to a JOIN record.

### Can I stop an agent from deleting or changing things in JOIN?

Yes. Restrictions in Elaichi apply per action, so you can allow reading JOIN jobs and candidates while blocking deleting applications or notes, or blocking any updates at all. A restricted action is never advertised to Claude, ChatGPT, or Cursor, so no prompt can reach it.

### What happens to a JOIN connection when someone leaves?

Offboarding a person in Elaichi ends their access to JOIN at once, in every client they used. A shared JOIN connection keeps working for everyone else on the team. If you want JOIN gone entirely, disconnecting it once in Elaichi removes it from Claude, ChatGPT, Cursor, and every other client.

### Does the JOIN MCP connector work with Gemini, Codex, Claude Code or other MCP clients?

Yes. JOIN is reached over the same MCP endpoint every client uses, so anything that speaks MCP can call it — Gemini, Codex, Claude Code, Windsurf, Cline, Zed and OpenCode among them — alongside Claude, ChatGPT, Cursor, and the Elaichi Agent. The tools on offer and the access behind them are identical whichever client asks. Only the setup screen differs.

### Is Elaichi an alternative to Zapier MCP for JOIN?

Yes. Both let Claude, ChatGPT or Cursor use JOIN. Zapier MCP fits a team that already automates in Zapier, since each person signs in and acts as themselves in that account. Elaichi fits when IT wants one address for the whole company, per-tool rules by role, and a record of every JOIN call.

### How is Elaichi different from Composio for JOIN?

Composio gives AI agents tools and sign-in handling across 1,000+ apps, for developers building agents or people using an assistant, billed per tool call. Elaichi gives a company's own people governed access to JOIN: one address, restrictions per role or user, and $15 per user per month. Both have role permissions and a log of every call.

## All 30 JOIN tools

Every tool below is callable through https://api.elaichi.ai/mcp once JOIN is connected, subject to the toolbox it is in and the restrictions on the caller.

- **List all JOIN jobs** (List). List jobs in Join. Truto sends status=ONLINE,OFFLINE,ARCHIVED and content=true by default (every job, with its full content); pass status or content to override (JOIN's own defaults are ONLINE and false). Returns each job's id, createdAt, lastUpdatedAt, title, status, externalId, and office.
- **Get single JOIN job by ID** (Get). Get a single job in Join by id. Returns the job including id, createdAt, lastUpdatedAt, title, status, externalId, office, workplaceType, and screening questions.

JOIN's reference says description, salary, contact, contactPerson, attachments, employmentTypeId, categoryId, seniorityId, language, and followers are returned only when content=true, yet documents no content parameter for this endpoint, so they may be absent. Required: id.
- **Create a JOIN job** (Create). Create a job in Join; new jobs are automatically set active and multiposted to job boards. Returns: id. Required: title, description, categoryId, language, employmentTypeId, officeId.
- **Update a JOIN job by ID** (Update). Update a job in Join by id; all body fields are optional. Returns: id. Required: id.
- **JOIN jobs bulk change status** (Action). Change the status of a job in Join to ONLINE, OFFLINE, or ARCHIVED. Returns: id. Required: job_id, status.
- **JOIN jobs activate** (Activate). Activate an archived job in Join. Once activated, the job is multiposted on job boards again. Returns: id. Required: job_id. This endpoint is deprecated; if the job is already active, an error is raised but the job remains active.
- **JOIN jobs archive** (Archive). Archive an active job in Join. Once archived, the job is no longer multiposted on job boards. Returns: id. Required: job_id. This endpoint is deprecated; if the job is already archived, an error is raised but the job remains archived.
- **List all JOIN applications** (List). List applications in Join with filters for job, country, dates, integration external id, hiring state, and stage type.

Returns: id, createdAt, lastUpdatedAt, attachments, source, job, candidate, screeningQuestions, consent, integrationExternalId, state, hiringState, pipelineStage, currentStage.

The deprecated state filter cannot be combined with hiringState or stageType; removed 2026-11-01. The stageType filter must be combined with hiringState.
- **Get single JOIN application by ID** (Get). Get a single application in Join by id. Returns: id, createdAt, lastUpdatedAt, attachments, source, job, candidate, screeningQuestions, consent, integrationExternalId, state, hiringState, pipelineStage, currentStage. Required: id.
- **Create a JOIN application** (Create). Create an application in Join by adding a candidate to a job, with optional base64-encoded documents, source channel, and integration external id. Returns: id. Required: candidate (email, firstName, lastName) and jobId.
- **Delete a JOIN application by ID** (Delete). Delete an application in Join by id. Returns: message. Required: id.
- **JOIN applications bulk update external data** (Update). Update an application's integration data with a new external id in Join. Returns: applicationId, integrationExternalId. Required: application_id, integrationExternalId.
- **JOIN applications bulk update** (Update). Update the tags of an application in Join. Returns: message. Required: application_id and tags. This endpoint is deprecated.
- **List all JOIN candidates** (List). List Join candidates belonging to the authenticated company. Returns: id, firstName, lastName, email, phone, country, source, tags, professionalLinks, consent, applications, notes, createdAt. Supports fuzzy search by email or name, filtering by creation date, and embedding candidate notes.
- **Get single JOIN candidate by ID** (Get). Get a single Join candidate by id. Returns the full candidate object: id, firstName, lastName, email, phone, country, source, tags, professionalLinks, consent, applications, notes, createdAt. Required: id.
- **Update a JOIN candidate by ID** (Update). Update a Join candidate's tags by id. Returns the updated candidate object including its id. Required: id. The provided tags array replaces all of the candidate's current tags.
- **List all JOIN notes** (List). List all notes for a candidate in Join. Returns: id, userEmail, content, createdAt, lastUpdatedAt, isPrivate, replies. Required: candidate_id. Up to 50 notes per page.
- **Create a JOIN note** (Create). Create a note for a candidate in Join. Returns the created note including id, userEmail, content, createdAt, lastUpdatedAt, and isPrivate. Required: candidate_id and content.
- **Update a JOIN note by ID** (Update). Update the content of a candidate note in Join. Returns the updated note including id, userEmail, content, createdAt, lastUpdatedAt, and isPrivate. Required: candidate_id, id, and content.
- **Delete a JOIN note by ID** (Delete). Delete a candidate note in Join. Returns a confirmation message (e.g. 'Note deleted'). Also deletes all replies of the note. Required: candidate_id and id.
- **List all JOIN offices** (List). List all offices in Join, optionally filtered by country code or city name (partial match). Returns: id, name, countryIso, city, streetName, streetNumber, postalCode, isDefault.
- **Get single JOIN office by ID** (Get). Get a single office in Join by id. Returns: id, name, countryIso, city, streetName, streetNumber, postalCode, isDefault. Required: id.
- **Create a JOIN office** (Create). Create an office in Join. Returns: id. Required: city, countryIso. Only one office can be the default (isDefault) at a time.
- **Update a JOIN office by ID** (Update). Update an office in Join by id. Returns: id. Required: id. All body fields are optional; streetName, streetNumber, and postalCode are nullable.
- **List all JOIN categories** (List). List all categories in Join, optionally translating the response via the language parameter (defaults to en). Returns each category with its id, slug, name, and subCategories (each with id, slug, and name). A job's category must be one of the sub-categories listed here.
- **List all JOIN employment types** (List). List all employment types in Join. Returns: id, slug, name. An optional language parameter translates the response (defaults to en).
- **List all JOIN scorecards** (List). List all scorecards submitted for a specific application in Join. Returns each scorecard's id, submittedBy (with userId, firstName, lastName, email), overAllRecommendation, overAllImpression, dateOfSubmission, createdAt, updatedAt, attributes (name and rating), and questions (id, question, and answer). Required: application_id.
- **List all JOIN seniority levels** (List). List all seniority levels in Join. Returns: id, slug, name.
- **JOIN attachments download** (Download). Download an application attachment from Join by id and external file name, using the sig signature JOIN puts in each attachment url (see applications.get). The response is the raw file (JOIN documents application/pdf), not JSON. Required: attachment_id, external_file_name, sig.
- **JOIN application files download** (Download). Download an application file from Join by id and external file name, using the sig signature. The response is the raw file (JOIN documents application/pdf), not JSON. Required: application_file_id, external_file_name, sig.
