MCP Server for AI Agents: Multi-ATS Career Jobs Search
Pricing
Pay per usage
MCP Server for AI Agents: Multi-ATS Career Jobs Search
Standby MCP Server (/mcp) and JSON API for AI agents to search live public job postings across 71 companies + any public career board URL on Greenhouse, Lever, Ashby, SmartRecruiters, and Workable with normalized USD salary, remote/hybrid filters, and incremental deduplication.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Mutualistic Labs
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
3 days ago
Last modified
Categories
Share
Standby MCP Server for AI Agents: Multi-ATS Career Jobs Search
An always-on Model Context Protocol (MCP) server for AI agents (Claude Desktop, Cursor, Windsurf, OpenAI Agents, LangChain) to search live public job postings across 71 built-in companies + any public career board URL on five applicant tracking systems: Greenhouse, Lever, Ashby, SmartRecruiters and Workable. Results are normalized (USD salary, remote/hybrid filters, incremental deduplication). Only official, unauthenticated public job-board JSON APIs are used: no scraping, no logins, no proxies.
The Actor runs in two modes on a single codebase:
- Standby MCP mode (primary): an MCP server at
/mcpexposing thesearch_jobsandlist_supported_companiestools to AI agents. - Batch dataset mode: provide input, get a clean, de-duplicated dataset.
Quick start: MCP for AI agents
Standby URL: https://mutualistic-housing--multi-ats-career-jobs-mcp.apify.actor/mcp (authenticate with your Apify API token).
Claude Desktop (claude_desktop_config.json, via the mcp-remote bridge):
{"mcpServers": {"ats-jobs": {"command": "npx","args": ["-y", "mcp-remote","https://mutualistic-housing--multi-ats-career-jobs-mcp.apify.actor/mcp","--header", "Authorization: Bearer <APIFY_API_TOKEN>"]}}}
Cursor (.cursor/mcp.json):
{"mcpServers": {"ats-jobs": {"url": "https://mutualistic-housing--multi-ats-career-jobs-mcp.apify.actor/mcp","headers": { "Authorization": "Bearer <APIFY_API_TOKEN>" }}}}
Tool call examples (JSON-RPC tools/call):
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_jobs","arguments":{"query":"python engineer","remoteOnly":true,"minAnnualSalaryUsd":150000,"maxItems":10}}}{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_supported_companies","arguments":{"atsProviders":["greenhouse","ashby"]}}}
Batch dataset mode is described under Input below.
Features
- Unified
NormalizedJobschema across all providers (deterministic SHA-256uid, UTC timestamps, workplace type, structured compensation). - Built-in curated registry of 71 built-in companies + any public career board URL, or bring your own slugs / career URLs.
- Filters: keyword query, locations, remote only, posted within N hours, only new since a date, minimum annual USD salary, excluded job IDs.
- Clean plain-text descriptions (HTML stripped, entities decoded).
- Resilient fetching: timeouts, retry with backoff on 429/5xx, dead company slugs (404) skipped without failing the run.
- Hard spending caps:
maxItemsandmaxTotalChargeUsdare never exceeded. Invalid input is rejected withINVALID_INPUT_ZERO_CHARGEbefore any network call or charge.
Supported providers
| Provider | Public API used |
|---|---|
| Greenhouse | https://boards-api.greenhouse.io/v1/boards/{slug}/jobs?content=true |
| Lever | https://api.lever.co/v0/postings/{slug}?mode=json |
| Ashby | https://api.ashbyhq.com/posting-api/job-board/{slug}?includeCompensation=true |
| SmartRecruiters | https://api.smartrecruiters.com/v1/companies/{slug}/postings |
| Workable | https://apply.workable.com/api/v1/widget/accounts/{slug} |
Recognized career URL formats: boards.greenhouse.io/{slug}, job-boards.greenhouse.io/{slug}, jobs.lever.co/{slug},
jobs.ashbyhq.com/{slug}, jobs.smartrecruiters.com/{slug}, apply.workable.com/{slug} (EU variants, www., trailing paths and query strings are handled).
SmartRecruiters slugs are case-sensitive (e.g. Visa, BoschGroup).
Input
| Field | Type | Description |
|---|---|---|
query | string | All whitespace-separated tokens must appear in title, department, team or description. |
companySlugs | string[] | provider:slug (e.g. greenhouse:stripe) or bare slug (tried on every selected provider). |
careerUrls | string[] | Public board URLs; provider and slug are extracted automatically. |
atsProviders | string[] | Subset of greenhouse, lever, ashby, smartrecruiters, workable. Empty = all. |
locations | string[] | Keep jobs whose location contains any substring (case-insensitive). |
remoteOnly | boolean | Only remote jobs. |
minAnnualSalaryUsd | number | Annualized upper-bound USD salary threshold. Jobs without USD pay are excluded. |
postedWithinHours | number | Published (or updated) within the last N hours. |
onlyNewSince | string | ISO-8601 date/time; only jobs published after it (incremental runs). |
excludeJobIds | string[] | uid or external_id values to skip. |
includeDescription | boolean | Include description_plain (default true). |
maxItems | integer | 0 to 10000, default 100. |
maxTotalChargeUsd | number | Hard budget cap in USD for the run. |
If both companySlugs and careerUrls are empty, the built-in registry is searched (filtered by atsProviders).
Example:
{"query": "python engineer","companySlugs": ["greenhouse:stripe", "ashby:openai", "lever:palantir"],"remoteOnly": true,"minAnnualSalaryUsd": 150000,"maxItems": 50}
Output
Each dataset item (snake_case):
| Field | Description |
|---|---|
uid | SHA-256 of provider:slug:external_id |
ats_provider, company_slug, company_name, external_id | Source identification |
title, department, team, employment_type | Job attributes |
workplace_type | remote, hybrid, onsite or unspecified |
locations, is_remote | Locations list and remote flag |
published_at, updated_at | ISO-8601 UTC (YYYY-MM-DDTHH:MM:SSZ) |
compensation | {min_amount, max_amount, currency, interval, raw_text} or null |
apply_url, source_api_url | Application link and API endpoint used |
description_plain | Plain-text description (when enabled) |
Standby MCP mode
When the Actor runs in Standby mode it serves HTTP on the Standby port:
GET /healthreturns200 {"status":"ok"}.POST /mcpaccepts JSON-RPC 2.0:initialize,ping,tools/list,tools/call.
Tools:
search_jobs: same arguments as the batch input (camelCase;maxItemsdefaults to 20). ReturnsstructuredContentwithjobs,countandcharged.list_supported_companies: lists the built-in registry, optionally filtered byatsProviders.
Example MCP client configuration (replace the token):
{"mcpServers": {"ats-jobs": {"url": "https://mutualistic-housing--multi-ats-career-jobs-mcp.apify.actor/mcp","headers": { "Authorization": "Bearer <APIFY_API_TOKEN>" }}}}
Quick check:
curl -X POST "https://mutualistic-housing--multi-ats-career-jobs-mcp.apify.actor/mcp" \-H "Authorization: Bearer <APIFY_API_TOKEN>" -H "Content-Type: application/json" \-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_jobs","arguments":{"query":"data scientist","maxItems":5}}}'
Pricing
This Actor is currently Free to use (Pay for usage): there is a $0.00 Actor fee. You only pay the standard Apify platform compute usage on your own Apify account.
The maxItems and maxTotalChargeUsd hard caps are enforced in code (src/billing.py and .actor/pay_per_event.json), so runs never exceed the limits you configure. Invalid input is never charged.
Limitations
- No descriptions for SmartRecruiters and Workable. Their public list endpoints do not include job descriptions or compensation. For these providers,
querymatches only the title and metadata (department, team, location), and compensation/minAnnualSalaryUsdcannot be derived. Searching "python" will miss jobs whose title lacks the word. - EU boards. Greenhouse and Lever EU career URLs (
boards.eu.greenhouse.io,job-boards.eu.greenhouse.io,jobs.eu.lever.co) are detected as EU boards. Lever EU career URLs (jobs.eu.lever.co) are fetched fromapi.eu.lever.co. Greenhouse EU career URLs (boards.eu.greenhouse.io,job-boards.eu.greenhouse.io) are served viaboards-api.greenhouse.io(the EU board API host does not resolve). The region is tracked per request/target; there is no process-global state, so an EU URL never affects later requests. Built-in registry entries are US-hosted; supply EU boards throughcareerUrls. - SmartRecruiters pagination cap. Pagination stops after 10 pages of 100 (1000 postings per company). If a company has more, a warning is logged, the fetch result is flagged
truncated, and the run/MCPerrorslist gets atruncated_at_1000entry withseverity: "warning"; the remaining postings are not returned. - Pay-per-event limits. The platform's charge limit is respected: when the run's max total charge is reached, items beyond the limit are not returned (neither pushed to the dataset nor returned by MCP
search_jobs), in addition to themaxItemsandmaxTotalChargeUsdcaps. The remaining platform charge capacity is read before every charge, in both batch and Standby mode (shared across all MCP calls of a run), so nothing is delivered once the limit is exhausted.
Notes
- Only publicly available job postings are accessed. Respect each company's terms when reusing the data.
- Company slugs that do not exist are reported in the run log and skipped.