zoho-recruit-mcp
v0.1.0
Published
Local MCP server for the Zoho Recruit API v2
Maintainers
Readme
Zoho Recruit MCP Server
A local Model Context Protocol (MCP) server that lets Claude read and write your Zoho Recruit data — job openings, candidates, interviews, and applications — directly from a conversation.
What it does
This server exposes the Zoho Recruit API v2 to any MCP client (Claude Code, Claude Desktop, etc.) as a set of tools. Ask Claude things like:
- "List the open job openings assigned to me."
- "Find candidates with the status 'Interview Scheduled'."
- "Create a new candidate for the Senior Engineer role."
- "Update interview #123 to next Tuesday at 2pm."
It handles OAuth access-token refresh automatically — you supply a long-lived refresh token once, and the server mints short-lived access tokens as needed. It speaks MCP over stdio, so it runs as a local subprocess of your client; no hosting required.
Table of contents
- Install
- Connecting to Claude
- Authentication (one-time Zoho setup)
- Available tools
- Customising the tools
- Development
- Notes
Install
Prerequisites: Node.js ≥ 18 and a Zoho Recruit account.
You don't need to clone or build anything — the package is published to npm and runs with npx:
npx -y zoho-recruit-mcpnpx downloads the prebuilt package and runs it. You'll need Zoho OAuth credentials before the server can talk to the API — see Authentication for a one-time walkthrough. Most users won't run this command directly; instead point Claude at it (next section), which manages the process for you.
Connecting to Claude
The server runs as a local subprocess. You point Claude at npx -y zoho-recruit-mcp and pass your Zoho credentials as environment variables.
Claude Code (CLI)
The fastest path — one command, no clone, no build:
claude mcp add zoho-recruit \
--env ZOHO_CLIENT_ID=1000.... \
--env ZOHO_CLIENT_SECRET=.... \
--env ZOHO_REFRESH_TOKEN=1000.... \
--env ZOHO_DC=com \
-- npx -y zoho-recruit-mcpThen start claude and ask it to list your job openings to confirm the connection.
Claude Desktop / Claude Code (config file)
Add the server to your client's MCP config (claude_desktop_config.json for Claude Desktop, or .mcp.json in your project for Claude Code):
{
"mcpServers": {
"zoho-recruit": {
"command": "npx",
"args": ["-y", "zoho-recruit-mcp"],
"env": {
"ZOHO_CLIENT_ID": "1000....",
"ZOHO_CLIENT_SECRET": "....",
"ZOHO_REFRESH_TOKEN": "1000....",
"ZOHO_DC": "com"
}
}
}
}Restart the client. The zoho-recruit tools will appear in Claude's tool list.
Run from source instead? Clone the repo,
npm install && npm run build, then usenode /absolute/path/to/zoho-recruit-mcp/dist/index.jsin place ofnpx -y zoho-recruit-mcp. Use an absolute path — relative paths resolve against the client's working directory.
Authentication (one-time Zoho setup)
The server uses the OAuth refresh-token grant. You need a client ID, client secret, and a refresh token, supplied via environment variables.
1. Register a client
At https://api-console.zoho.com create a Self Client (simplest for local use) or a Server-based Application. Note the Client ID and Client Secret.
2. Get a grant (authorization) code
Open this URL in a browser (replace the placeholders), authorize, and copy the code returned on the redirect:
https://accounts.zoho.com/oauth/v2/auth?scope=ZohoRecruit.modules.ALL&client_id=YOUR_CLIENT_ID&response_type=code&access_type=offline&redirect_uri=YOUR_REDIRECT_URIUse the accounts domain for your data center:
.com(US),.eu,.com.au,.in,.jp,.ca,.sa. For a Self Client, generate the code directly in the console instead of using a redirect URI.
3. Exchange the grant code for a refresh token
The grant code is valid for only a few minutes — exchange it immediately:
curl -X POST "https://accounts.zoho.com/oauth/v2/token" \
-d "grant_type=authorization_code" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "redirect_uri=YOUR_REDIRECT_URI" \
-d "code=GRANT_CODE"The response contains a refresh_token (long-lived) and an access_token (1 hour). Save the refresh token — this server uses it to mint fresh access tokens automatically.
4. Configure environment variables
Copy .env.example to .env, or pass the variables in your MCP client config (see Connecting to Claude):
| Variable | Required | Description |
| --- | --- | --- |
| ZOHO_CLIENT_ID | yes | OAuth client ID |
| ZOHO_CLIENT_SECRET | yes | OAuth client secret |
| ZOHO_REFRESH_TOKEN | yes | Refresh token from step 3 |
| ZOHO_DC | no | Data-center suffix: com (default), eu, com.au, in, jp, ca, sa |
| ZOHO_TOOLS_CONFIG | no | Path to a custom tools.yaml |
Available tools
Tools are defined in tools.yaml and loaded at startup. Each subject (a Zoho module) generates tools named <slug>_<operation>. The six operations map directly to the Zoho v2 methods:
| Operation | Zoho method | Tool example |
| --- | --- | --- |
| list | GET /{module} | job_openings_list |
| get | GET /{module}/{id} | job_openings_get |
| search | GET /{module}/search | job_openings_search |
| create | POST /{module} | job_openings_create |
| update | PUT /{module}/{id} | job_openings_update |
| delete | DELETE /{module}/{id} | job_openings_delete |
Default subjects: job_openings, candidates, interviews, applications (24 tools total).
Customising the tools
Edit tools.yaml and restart the server — no code changes needed:
- Add a module — copy a
subjectsblock, setslug,module,label,field_hint. - Make a subject read-only — set
operations: [list, get, search]. - Disable a subject — remove or comment out its block.
The config is validated on startup; bad slugs, unknown operations, or duplicate slugs fail fast with a clear message. To load a config from elsewhere, set ZOHO_TOOLS_CONFIG to its path (absolute, or relative to the working directory).
Development
git clone https://github.com/jonathanendy/zoho-recruit-mcp.git
cd zoho-recruit-mcp
npm install
npm run dev # tsc --watch
npm run typecheck # type-check without emitting
npm run build # compile to dist/ and copy tools.yaml
npm start # run the built serverVerify a build with a manual stdio handshake (dummy creds are fine for tools/list — no Zoho call is made until a tool runs):
printf '%s\n%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
| ZOHO_CLIENT_ID=x ZOHO_CLIENT_SECRET=y ZOHO_REFRESH_TOKEN=z node dist/index.jsPublishing (maintainers)
The package ships the prebuilt dist/ (see the files field); prepublishOnly rebuilds it automatically before each publish.
npm pack --dry-run # preview the tarball contents
npm version patch # bump the version + tag
npm publish # requires `npm login`Notes
- Access tokens expire hourly; the client refreshes them on demand and retries once on a
401. - All API calls target
https://recruit.zoho.<DC>/recruit/v2/. stdoutis reserved for the MCP protocol; logs go tostderr.
License
MIT
