jobzyn-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@jobzyn-mcpWhat candidates applied to job JZ-1001?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
JobZyn MCP server
Connect JobZyn to Claude Desktop, Codex, and other Model Context Protocol clients. This TypeScript server exposes one tool for each of the five documented JobZyn API endpoints, through either stdio or an optional Streamable HTTP /mcp endpoint.
The distribution is an npm package running locally over stdio. No hosted service is planned. Streamable HTTP remains available as an optional capability for independently managed installations; both transports use the same tools and validation.
Claude Desktop: use the automatic npx setup. Claude downloads and launches the package for you—no npm install, repository checkout, or absolute package path required. Node.js 22+ must already be installed.
npm package: jobzyn-mcp, version 0.1.1.
Contents
Related MCP server: HireFrog MCP
Features and endpoint coverage
API base URL: https://www.jobzyn.com/api/integrations.
MCP tool | API method and path | Scope | Behavior |
|
|
| Create a job; publishes immediately unless explicitly created as a draft |
|
|
| Change supplied fields; creates a missing job through an upsert |
|
|
| Remove public visibility while retaining job data |
|
|
| Retrieve one page of applications, with date filters |
|
|
| Attach external IDs to existing JobZyn jobs |
Coverage was checked against the JobZyn documentation on September 15, 2026. The site documents five method/path combinations. Authentication, accepted-values, and error pages describe those endpoints; they do not add API operations. There is no documented list-jobs endpoint or webhook registration endpoint to wrap.
Other features:
Typed, validated tool inputs, including all documented enums and query parameters.
Extra JSON fields inside
jobpass through, as allowed by JobZyn.Tool annotations identify read operations, writes, and changes that can remove or replace data.
Responses include both readable JSON text and MCP
structuredContent.Request timeouts, cancellation, bounded responses, and no automatic retries.
Authenticated HTTP, exact host/origin allowlists, and stateless request handling.
A CLI, TypeScript library exports, Dockerfile, and CI for Node.js 22 and 24.
Requirements and authentication
Node.js 22 or newer and npm for local execution or building.
A JobZyn company API key. In the JobZyn backoffice, a Company Admin can open Settings → API Keys → Generate New Key. Copy the key when it is shown.
readscope to retrieve candidates;writescope to create, update, unpublish, or link jobs. JobZyn binds each key to a company.
Set the key as JOBZYN_API_KEY. The server sends it to JobZyn in the x-api-key header. Tools never ask the model to provide an API key.
HTTP mode also needs a separate MCP_AUTH_TOKEN of at least 32 characters. Generate a random token with:
openssl rand -hex 32Use this token in the MCP client's Authorization: Bearer ... header. The server rejects a token that equals the JobZyn API key. The two credentials have different roles:
AI client ── MCP bearer token ──▶ JobZyn MCP server ── x-api-key ──▶ JobZynQuick start from source
git clone https://github.com/Yasmine-Works/jobzyn-mcp.git
cd jobzyn-mcp
npm ci
npm run build
cp .env.example .envEdit .env and replace JOBZYN_API_KEY with your company key. Then:
# Local MCP process; stdin/stdout belong to the MCP client.
node --env-file=.env dist/cli.jsThe stdio process waits for MCP messages, so a quiet terminal is normal. A client usually launches this process itself; you do not need to run a separate stdio server first.
.env is not loaded automatically. Use Node's --env-file option, set environment variables through your client, or have your hosting platform inject them. Never commit real credentials. npm start and npm run start:http use the current process environment.
Install from npm
npx downloads the pinned version into npm's cache and runs it. No separate npm install is needed. For Claude Desktop, skip the terminal commands and use the configuration below; Claude runs npx itself.
To launch it from a terminal:
export JOBZYN_API_KEY='YOUR_JOBZYN_API_KEY'
npx --yes jobzyn-mcp@0.1.1Or install the CLI globally:
npm install --global jobzyn-mcp@0.1.1
jobzyn-mcp --transport stdioTo try the package locally before publishing:
npm pack
npm exec --yes --package=./jobzyn-mcp-0.1.1.tgz -- jobzyn-mcp --helpPin reviewed releases in client configurations. Updating the package version requires updating and reviewing those pins as well.
Claude Desktop
Automatic install with npx (recommended)
Install Node.js 22 or newer, which includes npm and
npx, if it is not already installed.In Claude Desktop, open Settings → Developer → Edit Config.
Add the configuration below, replace
YOUR_JOBZYN_API_KEYwith your key, and save. If you already have other MCP servers, add only thejobzynentry inside the existingmcpServersobject.Fully quit and reopen Claude Desktop. The five
jobzyn_*tools should appear.
{
"mcpServers": {
"jobzyn": {
"command": "npx",
"args": ["--yes", "jobzyn-mcp@0.1.1"],
"env": {
"JOBZYN_API_KEY": "YOUR_JOBZYN_API_KEY"
}
}
}
}Claude launches npx, which downloads the package when needed and starts the local MCP server. --yes accepts npm's download prompt so startup can proceed without a terminal. Internet access is required for the first download and for calls to JobZyn. The version stays pinned until you change it in the configuration.
On Windows, use "command": "cmd" and "args": ["/c", "npx", "--yes", "jobzyn-mcp@0.1.1"] if launching npx directly fails.
This setup follows the official MCP local-server guide and npm's npx behavior. Protect the configuration file because it contains your API key. Standard locations are:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Run a source checkout (for development)
After building from source, you can run that checkout instead. Use this configuration with absolute executable and checkout paths:
{
"mcpServers": {
"jobzyn": {
"command": "/absolute/path/to/node",
"args": ["/absolute/path/to/jobzyn-mcp/dist/cli.js"],
"env": {
"JOBZYN_API_KEY": "YOUR_JOBZYN_API_KEY"
}
}
}
}On Windows, use an absolute node.exe path and escape backslashes in JSON. Fully quit and reopen Claude Desktop after saving.
Remote connections
For a client that supports custom authorization headers, configure the hosted HTTPS /mcp URL and the separate MCP bearer token. This server does not implement OAuth discovery, browser login, or dynamic client registration. If a Claude remote connector requires OAuth or cannot supply a custom bearer header, it needs a compatible authentication gateway in front of this server. Local stdio remains available without that gateway. Remote availability and authentication options depend on the client's managed configuration.
Codex
Local checkout
Add this entry to ~/.codex/config.toml, replacing the absolute paths:
[mcp_servers.jobzyn]
command = "/absolute/path/to/node"
args = ["/absolute/path/to/jobzyn-mcp/dist/cli.js"]
env_vars = ["JOBZYN_API_KEY"]Start Codex with JOBZYN_API_KEY available in its environment. If your desktop launcher does not inherit shell variables, use an absolute protected env-file path instead:
[mcp_servers.jobzyn]
command = "/absolute/path/to/node"
args = ["--env-file=/absolute/path/to/jobzyn-mcp/.env", "/absolute/path/to/jobzyn-mcp/dist/cli.js", "--transport", "stdio"]Choose one configuration for mcp_servers.jobzyn; do not duplicate the table.
Pinned npm package
Use the pinned npm package:
[mcp_servers.jobzyn]
command = "npx"
args = ["--yes", "jobzyn-mcp@0.1.1"]
env_vars = ["JOBZYN_API_KEY"]Hosted HTTP
The remote client does not need Node.js or the npm package:
[mcp_servers.jobzyn]
url = "https://mcp.example.com/mcp"
bearer_token_env_var = "JOBZYN_MCP_TOKEN"Set JOBZYN_MCP_TOKEN in Codex's environment to the server's MCP_AUTH_TOKEN. The client variable name is independent from the server variable name. You can also register the URL with the CLI:
codex mcp add jobzyn --url https://mcp.example.com/mcp --bearer-token-env-var JOBZYN_MCP_TOKEN
codex mcp listThe official Codex MCP documentation describes environment forwarding and bearer-token configuration. codex mcp login is for OAuth-enabled servers and is not the login mechanism for this static-token endpoint.
Streamable HTTP
This is an optional capability for independently managed installations. The planned npm distribution uses stdio and includes no hosted endpoint.
The implementation follows the SDK's Streamable HTTP guidance, using its stateless JSON-response mode. Each HTTP request receives its own MCP server and transport instance. There are no session IDs, in-memory client sessions, standalone SSE streams, or resumable event history.
Route | Access | Purpose |
| MCP bearer token | Initialize, discover tools, call tools, send notifications |
| No bearer token; origin validation applies | Browser CORS preflight |
| MCP bearer token | Returns |
| MCP bearer token | Returns |
| No bearer token; host validation applies | Liveness only; returns |
Requests include Content-Type: application/json and Accept: application/json, text/event-stream. Responses use JSON; valid notifications receive 202. The SDK handles protocol negotiation and rejects unsupported protocol-version headers. Returning 405 for an unsupported standalone GET stream is permitted by the MCP transport specification.
Local HTTP startup:
export JOBZYN_API_KEY='YOUR_JOBZYN_API_KEY'
export MCP_AUTH_TOKEN='YOUR_SEPARATE_RANDOM_MCP_TOKEN'
node dist/cli.js --transport httpThen check liveness and discovery from a second terminal with the token in its environment:
curl --fail http://127.0.0.1:3000/healthz
curl --fail http://127.0.0.1:3000/mcp \
-H "Authorization: Bearer $MCP_AUTH_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"manual-check","version":"1.0.0"}}}'
curl --fail http://127.0.0.1:3000/mcp \
-H "Authorization: Bearer $MCP_AUTH_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 2025-11-25' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'These checks do not create or modify jobs. /healthz does not verify your JobZyn credentials or upstream connectivity. The stateless server also accepts independent discovery requests; SDK clients perform the normal initialization exchange.
Hosting and Docker
No service will be hosted for this release. The following reference is only for operators choosing to host their own copy.
Deploy the Node process or container behind an HTTPS reverse proxy or security gateway. A typical configuration is:
JOBZYN_API_KEY=YOUR_JOBZYN_API_KEY
MCP_AUTH_TOKEN=YOUR_SEPARATE_RANDOM_MCP_TOKEN
MCP_TRANSPORT=http
HOST=0.0.0.0
PORT=3000
MCP_ALLOWED_HOSTS=mcp.example.com,127.0.0.1,localhostReplace mcp.example.com with the real hostname. MCP_ALLOWED_HOSTS validates the incoming Host hostname, ignoring its port. If the proxy rewrites Host to an internal service name, add that exact hostname. Forwarded host headers are not trusted. Do not use wildcards.
For browser-based clients that send an Origin header, add only the origins that should connect:
MCP_ALLOWED_ORIGINS=https://your-client.example.comOrigins include the scheme and optional port, with no trailing slash. Use the actual Origin sent by your client. Requests with an Origin header are rejected unless it is explicitly allowed; server-to-server requests without that header work with an empty list.
Build and run:
docker build -t jobzyn-mcp:0.1.1 .
docker run --rm --init --name jobzyn-mcp \
-p 127.0.0.1:3000:3000 \
--env-file .env \
-e HOST=0.0.0.0 \
-e MCP_TRANSPORT=http \
-e MCP_ALLOWED_HOSTS=mcp.example.com,localhost,127.0.0.1 \
jobzyn-mcp:0.1.1The container runs as the non-root node user. The example publishes the port only on the host's loopback interface for a local reverse proxy. Use your platform's private networking when the proxy runs elsewhere. The client URL is the public HTTPS address ending in /mcp, not the container address.
At the proxy/gateway:
Terminate TLS, authenticate callers, and forward the server's bearer token securely.
Preserve
Authorization,Accept,Content-Type, andMCP-Protocol-Version; do not log authorization headers or bodies.Allow MCP POST and any required CORS preflight. Set request timeouts above
JOBZYN_REQUEST_TIMEOUT_MS.Apply rate and concurrency limits appropriate to your JobZyn account. The package does not provide a distributed rate limiter.
Restrict network access so an organization gateway cannot be bypassed by connecting directly to the origin.
Use
/healthzfor liveness. Supply an allowed Host header for platform health probes.
Stateless replicas need no session affinity. Each deployment is configured for one JobZyn company. Run separately configured deployments for different companies, or build an authenticated tenant-to-credential mapping before offering a shared service.
No hosting provider or public hostname is provisioned by this repository. The Dockerfile is supplied for deployment; validate the image in your target environment.
Configuration reference
Variable | Default | Meaning |
| Required | Company API key, forwarded only as JobZyn's |
|
| Upstream integration root; HTTPS required, except HTTP on loopback for tests |
|
| Deadline for headers and response body, 1–300000 milliseconds |
|
|
|
| Required in HTTP mode | Separate bearer token, at least 32 characters; use a random value |
|
| HTTP listen address; use |
|
| HTTP listen port, 1–65535 |
| Loopback hosts when bound to loopback | Comma-separated exact hostnames/IPs, no scheme or port; required for non-loopback binding |
| Empty | Comma-separated exact browser origins; empty rejects all requests that include Origin |
HTTP-specific configuration is only required in HTTP mode. Base URLs may not include embedded credentials, query parameters, or fragments. Changing the base URL changes where the API key is sent; configure only trusted JobZyn environments. Tool inputs cannot change it.
CLI options:
jobzyn-mcp [--transport stdio|http]
jobzyn-mcp --help
jobzyn-mcp --versionThe HTTP request-body limit is 1 MiB. Upstream responses are limited to 10 MiB. Reduce candidate pageSize or split mapping batches if needed. Upstream API limits still apply.
Tool reference
Examples below are tool argument objects, used with the named MCP tool. A raw MCP call wraps them in {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"TOOL_NAME","arguments":{...}}}.
jobzyn_create_job
Required: job.id and job.title.
{
"job": {
"id": "REQ-2026-001",
"title": "Software Engineer",
"description": "<p>Build recruiting tools with our team.</p>",
"city": ["Casablanca", "Rabat"],
"country": "Maroc",
"languages": ["fr", "en"],
"contractType": "CDI",
"educationLevel": "BAC +5",
"workMode": "HYBRID",
"minSalary": 8000,
"maxSalary": 12000,
"displaySalary": true,
"minExperience": 0,
"maxExperience": 5,
"status": "UNPUBLISHED",
"recruitmentProcess": ["Screening", "Technical interview"],
"atsDepartment": "Engineering"
}
}This example creates a draft. Omitting status lets JobZyn default to PUBLISHED, so the job goes live immediately. A duplicate company/external-ID combination returns 409; use the update tool when appropriate.
All job fields
Field | Type | Notes |
| string | Required for create; your ATS identifier, used in later operations |
| string | Required for create |
| string | HTML supported; JobZyn sanitizes it |
| string | HTML supported |
| string | HTML supported |
| string or string[] | Text or a list |
| string or string[] | One or multiple city names |
| string | JobZyn creation default: |
| string[] |
|
| string |
|
| string |
|
| string |
|
| number | Net monthly salary bounds |
| boolean | JobZyn creation default: |
| number | Each between 0 and 20 years |
| string |
|
| string[] | Ordered interview/recruitment steps |
Additional fields | JSON values | Preserved inside |
Enums are case- and space-sensitive. The documentation's create example uses Bac+5, but the accepted-values page explicitly requires BAC +5; this server follows the accepted-values list. It does not normalize or silently substitute values. Unknown top-level tool arguments are rejected; custom fields belong inside job.
jobzyn_update_job
Required: externalJobId and a job object. Job fields are optional and only supplied fields are forwarded, so defaults do not overwrite existing data. false, 0, empty strings, and arrays are preserved.
{
"externalJobId": "REQ-2026-001",
"job": {
"title": "Senior Software Engineer",
"displaySalary": false,
"status": "PUBLISHED"
}
}This example publishes the job. The endpoint is an upsert: it updates an existing job (200) or creates a missing one (201). Include enough creation data, including a title, if the job may not exist. JobZyn accepts all create fields on update, including optional job.id; normally omit that field and use externalJobId to identify the target. The server forwards supplied values without rewriting the ID.
jobzyn_unpublish_job
{ "externalJobId": "REQ-2026-001" }The server sends DELETE with no body. Job data is retained, but candidates can no longer see the job publicly. To republish, call the update tool with job.status set to PUBLISHED.
jobzyn_get_candidates
{
"externalJobId": "REQ-2026-001",
"from": "2026-07-01T00:00:00Z",
"to": "2026-07-31T23:59:59Z",
"page": 1,
"pageSize": 50
}Parameter | Meaning |
| Required; your ATS job ID |
| Applications after this date; JobZyn gives it priority over |
| Applications on or after this date |
| Applications on or before this date |
| Integer starting at 1; JobZyn defaults to 1 |
| Integer 1–100; JobZyn defaults to 50 |
Dates accept ISO calendar dates such as 2026-07-01 or ISO timestamps with Z or a UTC offset. Prefer UTC timestamps for polling. All supplied filters are forwarded, including both since and from; JobZyn applies precedence.
Each call retrieves one page. Use the top-level data.total and your effective pageSize to determine how many pages remain. Candidate records may include application ID, name, email, phone, application date, status, cover message, LinkedIn URL, CV URL, and job/company references. CV URLs are returned as data; this server does not download resumes or open links.
For polling, keep a checkpoint in your own application, retrieve every page in a fixed date window, and advance the checkpoint only after processing that window successfully. A small overlap with deduplication by application id can protect against timestamp boundary or arrival-order issues. The documentation does not promise snapshot-stable pagination. The server does not retain polling state or run a scheduler. JobZyn documents polling as the current alternative to webhooks.
jobzyn_link_external_ids
{
"links": [
{ "jobzynJobId": 2625, "externalJobId": "REQ-2026-001" },
{ "jobzynJobId": 2626, "externalJobId": "REQ-2026-002" }
]
}jobzynJobId is JobZyn's internal numeric job ID, available in the backoffice job URL. externalJobId is your external ATS ID. This is the only tool that needs internal IDs.
Each result has one of three documented statuses:
linked: mapping was created.already_linked: the job already has an external ID; no change was made. This does not prove that the existing ID equals the one requested.not_found: the job does not exist or is outside the API key's company.
Inspect every result. A batch can partly succeed even with HTTP 200. The MCP result sets isError: true if any mapping is not_found, while retaining all successes and statuses. Existing mappings are not overwritten.
Results and errors
A successful call returns the upstream HTTP status and JobZyn response body:
{
"httpStatus": 200,
"data": {
"jobId": 1234,
"jobUrl": "https://www.jobzyn.com/fr/companies/example/jobs/example-job",
"error": null
}
}This object appears in MCP structuredContent and is serialized in a text content block. Upstream response fields remain available; an accidental echo of the configured API key is redacted.
API failures retain httpStatus and the response body and set MCP isError: true. Application-level error fields and partial link failures also set isError. If present, the upstream Retry-After header appears as retryAfter. An HTTP MCP request can return 200 while the enclosed tool result reports a JobZyn error: check isError and httpStatus.
JobZyn status | Typical action |
| Correct required fields, dates, or enum values |
| Check key, scopes, company ownership, and external job ID |
| Check the job ID; unpublish documents this for missing jobs |
| Job exists; consider update instead of create |
| Respect any retry guidance; reduce request rate |
| Investigate upstream failure; verify write outcome before repeating |
JobZyn's authentication page describes missing credentials as 403, while its error guide lists 401; the server preserves the actual upstream status. Candidate lookup can also return 403 for an unknown or inaccessible job.
Transport failures use a safe local error envelope:
{
"error": {
"code": "TIMEOUT",
"message": "JobZyn request timed out.",
"outcomeUnknown": true,
"guidance": "The write may have completed. Verify the job in JobZyn before repeating the request."
}
}Other codes include CANCELLED, NETWORK_ERROR, INVALID_RESPONSE, RESPONSE_TOO_LARGE, and INTERNAL_ERROR. An outcomeUnknown warning accompanies failed write transport/response handling. The server never retries automatically. Cancellation or timeout cannot roll back a request that JobZyn already applied.
Security and operating model
Single company per process/deployment. Every bearer-token holder can use the configured company's API scopes. The static token is not a user identity or tenant selector.
Gateway authentication. The bearer token is a shared deployment secret, not a complete MCP OAuth authorization service. Add the authentication and authorization gateway your managed client requires.
Secret separation. MCP authorization headers are not forwarded to JobZyn. Incoming
x-api-keyheaders cannot select a different upstream account.Restricted outbound requests. Only the five fixed endpoint shapes can be called. External job IDs are URL-encoded;
.and..path segments are rejected. Redirects are not followed, and production upstream URLs require HTTPS.Browser protections. Exact Host and Origin checks apply as documented above. CORS is not authentication; bearer authentication is still required for actual MCP calls.
Tool policy. Only candidate retrieval is marked read-only. Annotation hints help clients present approvals; they do not replace JobZyn scopes or gateway enforcement. Use a read-scoped JobZyn key and client/gateway tool restrictions for candidate-only access. All five tools remain discoverable.
Candidate privacy. Tool responses can contain personal information. Control who can invoke candidate retrieval and where your client retains responses. The server has no persistent application database and does not log tool bodies, but client/gateway infrastructure may retain them.
Untrusted content. Treat returned candidate text and job HTML as data, not instructions. The server does not execute returned content or follow resume links.
Shutdown. SIGINT/SIGTERM closes the transport/listener; HTTP gets up to 10 seconds to drain before forced exit. A process termination may leave an upstream write outcome uncertain.
Development, testing, and releases
npm ci
npm run check
npm test
npm run verify:packagenpm test builds the executable and runs tests against a local mock API using the actual MCP SDK clients. The suite verifies all five endpoints through both stdio and Streamable HTTP, custom-field preservation, input validation, request encoding, authorization/origin/host checks, concurrent clients, errors, partial successes, redaction, redirect refusal, and timeouts. It does not require credentials or mutate live JobZyn data. Live account behavior must be validated separately.
For source development, use npm run dev with credentials in the process environment. CLI diagnostics go to stderr so stdout remains valid MCP traffic.
Project layout
src/
cli.ts CLI, transport selection, shutdown
config.ts Environment parsing and configuration validation
schemas.ts All job fields and endpoint input schemas
client.ts Fixed JobZyn API operations and bounded HTTP requests
server.ts Five MCP tool registrations and result handling
http.ts Authenticated stateless HTTP app and listener
index.ts Public library exports
test/ Local API, MCP transport, validation, and error tests
examples/ Client configuration examplesLibrary usage
The package exports the MCP server factory, HTTP app/listener, typed API client, input schemas, and configuration readers. For example:
import { createJobzynServer, readApiConfig } from 'jobzyn-mcp';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = createJobzynServer(readApiConfig());
await server.connect(new StdioServerTransport());createHttpApp(apiConfig, httpConfig) lets an existing Express host mount the application. Keep its authentication and validation middleware intact. The JobzynClient methods are typed API wrappers; MCP input validation occurs in the server, so direct JavaScript callers should validate payloads with the exported schemas.
Live validation without stored credentials in code
Use an ignored local .env file containing JOBZYN_API_KEY, then run:
npm run build
npm run test:live -- --job-id YOUR_EXTERNAL_JOB_IDThe helper uses stdio, makes one read-only candidate lookup, and prints only status and counts. It never writes jobs, persists candidate records, or prints the API key or candidate details. No credentials are needed for CI or release preparation. See the live-test instructions.
Release process
Create the reviewed npm artifact with:
npm run release:prepareThis produces .release/jobzyn-mcp-0.1.1.tgz and an integrity manifest after checking the package allowlist, credentials, clean installation, TypeScript exports, and all five stdio tools. .release/, local .env* files, and .npmrc are excluded from Git. Only explicitly listed public files enter the package.
Follow the npm publication guide for the dry run, maintainer login, publication of the exact reviewed tarball, and registry verification. The npm examples for Claude Desktop and Codex are pinned to 0.1.1.
Confirm npm ownership/availability of
jobzyn-mcp, or change the package name and all client examples to your organization's scope.Update
package.json,src/config.ts's version, and client examples together. Commit the lockfile.Run the checks above. Inspect the tarball to confirm it contains compiled runtime files and declarations, README, examples, and LICENSE, with no secrets.
Test the tarball in a clean installation. Confirm the CLI works without source files or development dependencies.
Publish the reviewed version using your organization's npm release process. When publishing from the source directory,
prepublishOnlyruns the full release preparation gate andprepackbuilds the runtime.Record the published release metadata:
npm view jobzyn-mcp@0.1.1 version dist.integrity dist.tarball --jsonPublishing and hosting are separate actions. A public npm package has no public /mcp endpoint until someone deploys the HTTP server. No CI job in this repository publishes or deploys automatically.
Troubleshooting
Symptom | Check |
stdio appears to do nothing | It is waiting for a client; configure Claude/Codex to launch it |
JSON parsing errors in a local client | Launch the CLI directly; keep banners and logs off stdout |
|
|
| Publish the intended version first, or use the built checkout/tarball |
Claude cannot find | Install Node.js 22+ and fully restart Claude. If Node is installed through a version manager, ensure its executables are available to desktop apps; on Windows, try the |
Desktop cannot find Node | Set an absolute Node executable path; verify Node 22+ |
HTTP | Supply the separate MCP token, not the JobZyn API key |
HTTP | Check allowed Host and Origin; your proxy may rewrite Host |
HTTP | Expected; this endpoint uses Streamable HTTP POST and has no standalone SSE stream |
HTTP | Reduce the request below 1 MiB, e.g. split a link batch |
MCP tool returns JobZyn | Check API scopes, company ownership, and the external job ID |
| Use the exact accepted value with spaces and capitalization |
Missing candidates | Check date filters, |
Timeout while writing | Verify the job in the JobZyn backoffice before retrying |
HTTP startup fails on | Set explicit |
OAuth login fails | This server uses a static bearer token; configure headers or a compatible gateway |
Documentation sources
License
MIT, copyright 2026 Yasmine Works and Agenz.
Available Tools
5 toolsjobzyn_create_jobCreate JobZyn jobA
Create a job (POST /job, write scope). Requires job.id and job.title. Defaults to PUBLISHED: the job becomes public immediately. Set status UNPUBLISHED for a draft. Duplicate external IDs return 409. Additional job fields are preserved.
| Name | Required | Description | Default |
|---|---|---|---|
| job | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description reveals key write behavior: immediate publication by default, the UNPUBLISHED draft path, 409 on duplicate external IDs, and preservation of additional fields. This is substantial behavioral disclosure for annotations that only provide generic hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: endpoint and scope first, then requirements and behavior. Every sentence earns its place by stating a requirement or a behavioral consequence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a creation tool with no output schema, te description covers endpooint, required subfields, default status, draft option, duplicate behavior, and open-world field handling. It omits the response shape, but an agent has enough to invoke the tool correctly and understand common failures.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The top-level job parameter has no schema description, so the description compensates by identifying required id/title subfields and adding status and duplicate-ID semantics. It does not enumerate every optional field, but the nested schema already documents those details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Create a job (POST /job, write scope).' It also clarifies required fields and creation defaults, which clearly distinguishes it from siblings like jobzyn_update_job or jobzyn_get_candidates.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: job.id and job.title are required, and the caller must choose between PUBLISHED (immediate public) and UNPUBLISHED (draft). It does not explicitly name update_job as the alternative for existing IDs, but the duplicate-external-ID 409 behavior implies the boundary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jobzyn_get_candidatesGet JobZyn candidatesARead-onlyIdempotent
Retrieve one page of applications for an external job ID (GET /job/{externalJobId}/candidates, read scope). Supports since/from/to ISO dates and page/pageSize (1-based; default 50, max 100). since takes priority over from. Use total to fetch remaining pages. Contains personal information and resume URLs; no files are downloaded.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Applications on or before this date. | |
| from | No | Applications on or after this date; ignored by JobZyn when since is supplied. | |
| page | No | Page number, starting at 1. JobZyn defaults to 1. | |
| since | No | Applications after this date; takes priority over from when both are supplied. | |
| pageSize | No | Results per page, at most 100. JobZyn defaults to 50. | |
| externalJobId | Yes | Your external job ID from your ATS, not the internal numeric JobZyn job ID. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false. The description adds meaningful behavioral context: it mentions the read scope, clarifies that 'since takes priority over from', explains pagination via 'Use total to fetch remaining pages', and warns about personal information and that no files are downloaded. This goes well beyond the annotations and provides actionable operational insights.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, front-loaded with the core purpose, followed by essential operational details. Every sentence adds value: the purpose, the supported options, and the pagination/data-sensitivity note. No redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With six parameters but only one required, the schema covers all parameter meanings, and annotations cover safety. Since there is no output schema, the description provides some guidance on response usage ('Use total to fetch remaining pages') and alerts to personal information. It does not describe the candidate object structure, but for a paginated read tool that is likely sufficient for an agent to invoke correctly. Minor gap: no explicit mention of the response format beyond pagination.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% – every parameter has a description. The tool description repeats some schema details (default pageSize, 1-based page, priority rules) but adds little new parameter-level meaning. It does introduce the concept of using 'total' for pagination, which is output-related, not parameter-specific. Since the schema already documents each parameter thoroughly, the description does not significantly enhance parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action: 'Retrieve one page of applications for an external job ID' – a specific verb, resource, and scope. It also names the HTTP endpoint and read scope, distinguishing it from sibling tools like jobzyn_create_job or jobzyn_unpublish_job, which are mutations. The purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description conveys when to use this tool (to fetch candidate applications) and provides operational details (pagination, date filters, priority rules). It does not explicitly contrast it with alternatives, but the sibling names (create, update, unpublish, link) make the read-only distinction obvious. There is no misleading guidance; the context is clear but lacks an explicit 'use this instead of X' statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jobzyn_link_external_idsLink JobZyn external IDsAIdempotent
Link external ATS IDs to existing internal numeric JobZyn job IDs (POST /job/link, write scope). Existing external IDs are not overwritten. Inspect every result: linked, already_linked, or not_found. A batch can partially succeed.
| Name | Required | Description | Default |
|---|---|---|---|
| links | Yes | Mappings for existing JobZyn jobs. Existing external IDs are not overwritten. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide read/write and idempotency hints, but the description adds crucial detail: existing external IDs are not overwritten, result statuses include linked/already_linked/not_found, and batches can partially succeed. This goes beyond the structured annotations and sets accurate expectations for response handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler: purpose is front-loaded, followed by the two behavioral constraints that matter most (no overwrite, partial success). Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description compensates by enumerating result statuses and explicitly warning about partial success. For a single-parameter, low-complexity tool with annotations covering safety, this is complete enough for correct invocation and interpretation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already fully describes the links array, jobzynJobId, and externalJobId. The description does not add parameter-level semantics beyond restating these concepts, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Link') and resource ('external ATS IDs to existing internal numeric JobZyn job IDs'), and adds the endpoint and write scope. It clearly differentiates this from siblings like create, update, and unpublish by focusing on existing jobs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Context is clear: this links external IDs to existing internal IDs, so agents can infer it is not for creating or updating jobs. However, it does not explicitly name alternative tools or state 'use this only when jobs already exist', leaving some inference to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jobzyn_unpublish_jobUnpublish JobZyn jobADestructiveIdempotent
Unpublish a job by external ID (DELETE /job/{externalJobId}, write scope). Removes public visibility while retaining the job data. Does not permanently delete the job.
| Name | Required | Description | Default |
|---|---|---|---|
| externalJobId | Yes | Your external job ID from your ATS, not the internal numeric JobZyn job ID. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal write/destructive behavior, so the description adds value by clarifying the exact effect: 'Removes public visibility while retaining the job data' and 'Does not permanently delete the job.' It also includes 'write scope' and the HTTP method, giving the agent a clearer behavioral picture.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each earning its place: the first states the operation and endpoint, the second describes the state change, and the third clarifies what it does not do. There is no redundant or filler text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter tool with 100% schema coverage and annotations covering idempotency, read-only-ness, and destructiveness, the description is complete enough for an agent to invoke it correctly. It clarifies the non-destructive nature of unpublishing and does not need an output schema to explain return values.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter is fully documented in the schema with a clear description of externalJobId, including the warning that it is not the internal numeric JobZyn job ID. The description's 'external ID' phrasing adds little beyond the schema, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Unpublish a job by external ID') and gives the exact endpoint and scope. It is clearly distinct from the sibling tools (create, update, get, link), and it disambiguates 'unpublish' from permanent deletion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: use this when you need to remove public visibility while retaining data, and it explicitly says this does not permanently delete the job. It does not name alternative tools or state when to prefer update_job instead, but the intended usage is evident.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jobzyn_update_jobUpdate or upsert JobZyn jobADestructiveIdempotent
Update a job by external ID (PUT /job/{externalJobId}, write scope). Only supplied fields change. If the job does not exist, JobZyn creates it (201); include a title for creation. Can publish/unpublish through status. Job fields including optional id and custom fields are forwarded as supplied.
| Name | Required | Description | Default |
|---|---|---|---|
| job | Yes | ||
| externalJobId | Yes | Your external job ID from your ATS, not the internal numeric JobZyn job ID. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as read-write, destructive, idempotent, and open-world. The description adds valuable behavioral details beyond those flags: partial-update semantics, 201 creation on missing job, status-based publish/unpublish, and forwarding of custom fields. No contradiction with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences front-load the core operation and scope, then add the essential upsert, partial-update, and custom-field behavior. No filler or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with a nested job object and no output schema, the description covers the key call semantics: identification, partial update, creation fallback, title requirement, status effect, and custom fields. It stops short of describing response/error behavior, but the annotations and detailed input schema carry the rest.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is about 50%, and the description adds useful conditional semantics not explicit in schema: the external ID is the lookup key, title is required for creation, and unknown/custom job fields are passed through. It doesn't enumerate every parameter, but the schema already documents most field meanings.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific operation ('Update a job by external ID'), the HTTP method/resource (PUT /job/{externalJobId}), and the write scope. It also distinguishes itself from create by stating the upsert behavior: if the job does not exist, JobZyn creates it (201).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context: use external ID, only supplied fields change, creation requires title, and status can publish/unpublish. It does not explicitly name when to prefer sibling tools like jobzyn_create_job or jobzyn_unpublish_job, so it falls just short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.1- First observed
jobzyn_create_job - First observed
jobzyn_get_candidates - First observed
jobzyn_link_external_ids - First observed
jobzyn_unpublish_job - First observed
jobzyn_update_job
TDQS
Scored across 5 tools
Each tool has a distinct primary purpose: create, update, unpublish, fetch candidates, and link IDs. The only mild ambiguity is that update_job can also publish/unpublish via status, which overlaps with unpublish_job, but the dedicated unpublish action is still clearly differentiated.
All tools follow a consistent verb_noun snake_case pattern with the jobzyn_ prefix (create_job, update_job, unpublish_job, get_candidates, link_external_ids). No mixed conventions or vague verbs.
Five tools is well-scoped for a focused job-posting and candidate-retrieval MCP server. Each tool earns its place, and the count is neither too thin nor bloated.
The set covers create, update, unpublish, and candidate retrieval, but lacks a get_job or list_jobs operation, making it impossible to read or verify a job's current details or status through the MCP surface. This is a notable gap for a job-management server.
Maintenance
Related MCP Connectors
- Cavuno MCPOAuthcom.cavuno
Connect Claude, Cursor, Codex, and other MCP clients to manage your Cavuno job board.
Let AI agents query data and act across all your business apps via MCP.
7 recruiting tools over one MCP endpoint: ATS boards, LinkedIn jobs, profiles, companies, Naukri.
isolved and ApplicantPro jobs, tenant discovery, and change detection as an MCP server.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables AI assistants to recommend jobs, parse candidate profiles, compute semantic skill match scores, and filter opportunities by location through standardized MCP tools.-

HireFrog MCPofficial
AlicenseNot gradedqualityBmaintenanceEnables MCP-compatible AI assistants to securely access a user's job-search account, letting them search and save jobs, analyze job fit, and retrieve job queue and profile summaries with links back to the web app.MIT- AlicenseNot gradedqualityCmaintenanceEnables creating or selecting EasyHire AI jobs and importing complete candidate profiles through a hosted remote MCP server.Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables AI clients to serve as a personal career analyst by searching, matching, and explaining job recommendations, managing job applications, and syncing public job boards through standardized MCP tools.MIT