Skip to content

Fairquery Company Jobs Feed

com.getfairquery/company-jobs-feed-mcpgetfairquery.comstreamable-httpv1.1.9Scanned

Live jobs from Greenhouse, Lever, Ashby, Personio, Pinpoint and Gem with age and repost signals.

6 tools: 1 change things and 5 only read.

Tools: 0 delete, 0 irreversible, 1 write, 5 read.
  • Reads private data · 0
  • Reads text others write · 5
  • Can send data out · 0
  • 6 findings

Anlyon alternative

1 of these tools change something. Run those as governed actions.

Declare what an action changes, and Anlyon puts it under a shared limit, binds every approval to the exact request, and grades the outcome. It works on any HTTPS API you can describe as an action.

Anlyon does not run, proxy or govern this MCP server. A tool your own code calls directly is not routed through Anlyon and is not governed by it.

Import an OpenAPI spec →

Tools

Grouped by what each tool does, most consequential first. Open one for its reasons and full description; descriptions are the publisher's own words.

6 tools

Changes things 1Claude Code: ask
  • jobs_check_openWHAT: Re-check ONE job on the employer's ATS right now and report open or closed.Reads text others write2 findings

    Why it is in this group

    • The name "jobs_check_open" says "open": a word for a change.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.

    Findings

    • Info

      The description is 2,117 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...ey":"greenhouse:stripe:8172503"} -> {"status":"open","method":"detail_endpoint"}."

      What this check looks for
    • Warn

      The server marks "jobs_check_open" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

      Matched text

      annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}; The name "jobs_check_open" says "open": a word for a change.

      What this check looks for
    Description, as the server wrote it
    WHAT: Re-check ONE job on the employer's ATS right now and report open or closed. WHEN: Before applying, alerting or contacting about a specific job you got earlier (job_key or ats + slug + jobId), when you only need open or closed. WHEN NOT: One job's full detail (jobs_get_job). Listing a board (jobs_get_board). Checking many jobs at once (jobs_search_companies with confirmOpen, paid). BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs or results. The job id and board slug are sent to the public ATS host in the requests below. Greenhouse, Lever: one GET to the documented per-job endpoint; HTTP 404 = closed. Ashby has no per-job endpoint, so the whole board is fetched once and searched for the id (method "board_listing"). Personio has no per-job endpoint either: robots.txt, then the documented /xml feed only, and the position id is looked up (method "board_listing"). No apply URL is requested. "open" means currently published by the employer; it does not prove the role is still being filled. COST: No APIFY_TOKEN, no billing. RETURNS: One "open_check" row (job = the full "job" row when includeDescription=true and the job is open, else null), or a tool error: INVALID_INPUT, BOARD_NOT_FOUND, HOST_BLOCKED or NETWORK_ERROR (the last two retryable). PARAMETERS: A malformed jobKey, or neither jobKey nor a complete ats + slug + jobId, returns INVALID_INPUT without a request. An Ashby or Personio id costs one full board download (Personio is robots.txt plus /xml); on Greenhouse and Lever a 404 triggers one extra board request so a closed job (status closed) is told apart from a missing board (BOARD_NOT_FOUND). includeDescription adds no request on Greenhouse and Lever (the per-job response already holds the text) and makes the Ashby or Personio board download include descriptions; description_text is plain text, <= 20,000 chars, e-mails/phones removed, exactly as in jobs_get_board. EXAMPLE: {"jobKey":"greenhouse:stripe:8172503"} -> {"status":"open","method":"detail_endpoint"}.

    Annotations the server declares

    • title: Re-check whether one job is still published (free)
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: true
Only reads 5Show 5 read-only tools
  • jobs_find_boardWHAT: Resolve a company name, domain or careers/board URL to its public job board(s) on Greenhouse, Lever or Ashby.Reads text others write1 finding

    Why it is in this group

    • The name "jobs_find_board" says "find": a word for reading.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    • untrusted-inputThe description's first sentence says "url": it reads web pages, which anyone can write.

    Findings

    • Info

      The description is 3,144 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...p.com"} -> [{"ats":"ashby","slug":"ramp","via":"seed_list","confidence":"high"}]."

      What this check looks for
    Description, as the server wrote it
    WHAT: Resolve a company name, domain or careers/board URL to its public job board(s) on Greenhouse, Lever or Ashby. A Personio URL or personio:account you already know is parsed on this Worker and not looked up. WHEN: Before jobs_get_board when you only know the company ("Ramp", "sentry.io", "https://stripe.com/jobs") or you have a Personio career URL. WHEN NOT: You already have ats + slug (call jobs_get_board). For many companies plus their jobs in one step use jobs_search_companies (paid). It cannot find Workday, Workable, Recruitee, Rippling or LinkedIn pages, and it does not discover Personio accounts. BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs or results. Parts of the input are sent to public ATS hosts or the company site, as the steps below describe. Order: board-URL parsing (including personio:{account} and https://{account}.jobs.personio.de/..., no network) -> verified starter list -> the company's own website (only for a domain/URL input; robots.txt respected, <= 3 pages, private/internal IPs refused; Personio hosts are not crawled) -> at most 6 GETs against the Greenhouse, Lever and Ashby APIs with slug guesses. Personio is never probed and a careers-page link to Personio is ignored. Stops at the first hit. Nothing is cached or stored. Rate limits: max 2 parallel requests per host, Lever spaced 1 s apart, 15 s timeout per GET; ATS API network errors and HTTP 5xx are retried at most twice with backoff (0.5-1.6 s). Any HTTP 403/429 (or an HTML block page from an ATS API) stops that host for the session (kill switch, never retried, also for the other free tools): the call does not fail but adds a HOST_BLOCKED note to meta.notes, stops the careers-page step when the company site is blocked, and skips later slug probes on a stopped ATS host without sending them. COST: No APIFY_TOKEN and no billing; worst case about 4 website requests (robots.txt + 3 pages) and 6 ATS API GETs per call. RETURNS: "board" rows, or one NO_BOARD_FOUND error row. via (board_url | seed_list | careers_page | slug_probe) says how the board was found; confidence is "high" except for slug_probe hits ("medium": the slug exists but may belong to a different company with the same name, so check the jobs or pass the URL from the careers page). PARAMETERS: company accepts three forms with different behavior: a board URL (including a Personio account URL or personio:account) is parsed with no network call; a domain or https URL enables the careers-page step; a plain name only uses the starter list and slug probes. Slug guesses for a name drop legal suffixes and "the" (Inc, LLC, Ltd, GmbH, Corp, Co, PLC, AG, SA, BV) and try the joined words, the hyphenated words and the first word; probes run Greenhouse, Lever, Ashby in that order (never Personio) and the first hit wins, so an ambiguous name returns at most one medium-confidence board. A starter-list match can return several boards (all high). EXAMPLE: {"company":"ramp.com"} -> [{"ats":"ashby","slug":"ramp","via":"seed_list","confidence":"high"}].

    Annotations the server declares

    • title: Find which ATS board a company uses (free)
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: true
  • jobs_get_boardWHAT: Fetch every job currently published on ONE company board from its official public ATS API (Greenhouse, Lever or Ashby) or from Personio's documented XML feed for an account y…Reads text others write1 finding

    Why it is in this group

    • The name "jobs_get_board" says "get": a word for reading.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.

    Findings

    • Info

      The description is 2,476 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...gineer"],"remote":"only"} -> remote engineering roles at Ramp with salary ranges."

      What this check looks for
    Description, as the server wrote it
    WHAT: Fetch every job currently published on ONE company board from its official public ATS API (Greenhouse, Lever or Ashby) or from Personio's documented XML feed for an account you name, normalize it and filter it on this Worker. WHEN: You know the board (ats + slug), e.g. from jobs_find_board or a careers-page link, and want its live openings now. For Personio you already know the company subdomain. WHEN NOT: One known job's full detail (jobs_get_job). Many companies at once, history (new/closed/reposted since last run), or careers-page discovery at scale: use jobs_search_companies (paid). Unknown Greenhouse/Lever/Ashby board: use jobs_find_board first. Personio accounts are never discovered. SmartRecruiters, LinkedIn, Workday, Workable, Recruitee and Rippling are not supported and never contacted. BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs or results. The slug is sent to the public ATS host in the requests below. Greenhouse, Lever and Ashby: one GET to the documented API host only (very large Greenhouse boards: a second, lighter GET). Personio: robots.txt, then GET https://{account}.jobs.personio.de/xml only (no other path, query or apply URL); all Personio accounts share one lane, one request at a time, at least 1.5 s apart. Nothing stored, no history: first_seen_at = now and change = null. Any HTTP 403/429 stops that host for the session (kill switch, HOST_BLOCKED error). A blocked Personio account does not block other accounts. Lever requests are spaced 1 s apart (its robots.txt Crawl-delay). COST: No APIFY_TOKEN, no billing. RETURNS: Paged "job" rows. compensation only when the ATS publishes it; posted_at is the ATS date or null (never guessed); age_basis says how age_days was derived. PARAMETERS: All filters are AND-ed; values inside one filter are OR-ed. titleIncludes/titleExcludes match whole words ("engineer" does not match "Engineering"). countries uses the ATS's structured country where present (Lever, Ashby) and a place-name list otherwise; rows without any country are dropped when countries is set. postedWithinDays drops rows with posted_at = null. Paging re-fetches the board, so pages from different calls can shift if the employer edits the board in between. EXAMPLE: {"ats":"ashby","slug":"ramp","titleIncludes":["engineer"],"remote":"only"} -> remote engineering roles at Ramp with salary ranges.

    Annotations the server declares

    • title: Get live jobs from one ATS board (free)
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: true
  • jobs_get_jobWHAT: Fetch the full detail of ONE job that is currently published on its official public ATS API (Greenhouse, Lever or Ashby) or on a Personio XML feed for an account you name, no…Reads text others write1 finding

    Why it is in this group

    • The name "jobs_get_job" says "get": a word for reading.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.

    Findings

    • Info

      The description is 2,658 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...emoved. EXAMPLE: {"jobKey":"greenhouse:stripe:8172503"} -> that Stripe job's row."

      What this check looks for
    Description, as the server wrote it
    WHAT: Fetch the full detail of ONE job that is currently published on its official public ATS API (Greenhouse, Lever or Ashby) or on a Personio XML feed for an account you name, normalized the same way as a board listing, including its description. WHEN: You already have a job_key, or ats + slug + jobId, from jobs_get_board or a board link and need that single job's text, location, compensation and dates. WHEN NOT: Open or closed only (jobs_check_open). Every opening on a board (jobs_get_board). Many companies, history or repost signals (jobs_search_companies, paid). SmartRecruiters, LinkedIn, Workday, Workable, Recruitee and Rippling are not supported and never contacted. BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs or results. The job id and board slug are sent to the public ATS host in the requests below. Greenhouse and Lever: one GET to the documented per-job endpoint (the description is in that response). Ashby has no per-job endpoint, so the board is fetched once and the id is looked up. Personio has no per-job endpoint: robots.txt, then GET https://{account}.jobs.personio.de/xml only, and the position id is looked up. No apply URL is requested. HTTP 404/410 on Greenhouse or Lever, when the board itself exists, or an id missing from an Ashby or Personio board, is JOB_CLOSED (closed or unknown id) with no partial row. Nothing is stored. Any HTTP 403/429 stops that host for the session (kill switch, HOST_BLOCKED). Lever requests are spaced 1 s apart. Personio accounts share one lane, at least 1.5 s apart. COST: No APIFY_TOKEN, no billing. RETURNS: One "job" row, or a tool error: INVALID_INPUT, BOARD_NOT_FOUND, JOB_CLOSED, HOST_BLOCKED or NETWORK_ERROR (the last two retryable). A non-JSON body or other HTTP failure uses the ATS client code (ATS_BAD_RESPONSE, ATS_HTTP_ERROR). PARAMETERS: A malformed jobKey, or neither jobKey nor a complete ats + slug + jobId, returns INVALID_INPUT with no request. An Ashby id downloads the whole board with descriptions (one request, the same board GET as jobs_get_board with descriptions). A Personio id downloads the documented /xml feed (robots.txt plus /xml) and looks up the position id. Greenhouse and Lever use the per-job endpoint; a 404 or 410 triggers one extra board request so JOB_CLOSED is told apart from a missing board (BOARD_NOT_FOUND). description_text is always included when the job is open: plain text, at most 20,000 characters, e-mail addresses and phone numbers removed. EXAMPLE: {"jobKey":"greenhouse:stripe:8172503"} -> that Stripe job's row.

    Annotations the server declares

    • title: Get one published job's full detail (free)
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: true
  • jobs_list_seed_boardsWHAT: List the bundled starter list of company job boards that Fairquery verified on their official ATS APIs (company, domain, ats, slug, verified_at, jobs_at_verification).No findings

    Why it is in this group

    • The name "jobs_list_seed_boards" says "list": a word for reading.
    Description, as the server wrote it
    WHAT: List the bundled starter list of company job boards that Fairquery verified on their official ATS APIs (company, domain, ats, slug, verified_at, jobs_at_verification). WHEN: To pick companies to scan, or to know which names jobs_find_board resolves instantly. WHEN NOT: Live job data (jobs_get_board) or companies not in the list (jobs_find_board). The list is a starting point, not a global index of employers. BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs or results. No further network call: it reads a static list compiled into this Worker. jobs_at_verification is a snapshot from verified_at and goes stale. COST: No APIFY_TOKEN, no billing. RETURNS: Paged "seed_board" rows in the fixed bundled order (grouped by ATS, so offsets are stable). PARAMETERS: ats narrows the list; omit it for the whole starter list (Greenhouse, Lever, Ashby). Personio is not in the starter list (named accounts only). meta.by_ats always counts the whole list per ATS and ignores ats, so take paging totals from total. Feed ats + slug of any item straight into jobs_get_board. EXAMPLE: {"ats":"lever"} -> Palantir, Spotify, Zoox, Ro.

    Annotations the server declares

    • title: List the verified starter boards (free, offline)
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • jobs_search_companiesWHAT: Run the Fairquery Apify Actor fairquery/company-jobs-feed over many companies or boards: board discovery for Greenhouse, Lever and Ashby, a Personio XML feed when you name th…Reads text others write1 finding

    Why it is in this group

    • The name "jobs_search_companies" says "search": a word for reading.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.

    Findings

    • Info

      The description is 2,453 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...com","ramp.com"],"titleIncludes":["engineer"],"countries":["US"],"onlyNew":true}."

      What this check looks for
    Description, as the server wrote it
    WHAT: Run the Fairquery Apify Actor fairquery/company-jobs-feed over many companies or boards: board discovery for Greenhouse, Lever and Ashby, a Personio XML feed when you name the account, search filters, per-board history (first_seen/last_seen, new/updated/closed, repost detection), optional per-job re-checks and descriptions. WHEN: Monitoring a company list ("what is new since yesterday?"), searching the verified starter list, or anything that needs history, closed/repost signals or more than a few boards. WHEN NOT: One board right now (jobs_get_board), one job's full detail (jobs_get_job), or one open/closed re-check (jobs_check_open). BEHAVIOR: Read-only on job sites; requires APIFY_TOKEN. Called from this Fairquery-hosted Worker, which forwards your input and token to Apify and waits 20 s (APIFY_TIMEOUT if the run has not finished). The Actor runs in YOUR Apify account; history is kept in a named key-value store there. This Worker's code is designed not to store the input or token. Same politeness rules as the free jobs tools: documented ATS APIs only, Personio only at https://{account}.jobs.personio.de/xml after robots.txt, 403/429 kill switch, robots.txt on careers pages. Personio accounts are not discovered. Output is that run's rows, not a public jobs directory. COST: Paid, pay-per-event, billed to your Apify account: $0.99 per 1,000 jobs + $0.50 per 1,000 boards, plus optional $0.29 per 1,000 re-checks (confirmOpen) and $1.90 per 1,000 discovered companies; no start fee. Error, closed and merged rows are free. Example: 3 boards, 300 jobs = about $0.30. RETURNS: Paged dataset rows: "job" rows (as jobs_get_board plus first_seen_at, last_seen_at, change, reposted, repost_of, stale_signal, duplicate_of), one "board" row per board (jobs_total, new, updated, closed), "company" rows for discovery, "error" rows (code, message, retryable). PARAMETERS: companies, boards and useSeedList: at least one is required although the schema marks all optional (none -> INPUT_EMPTY, not billed). onlyNew implies history and compares with the last run that used the same stateStoreName, so use one name per saved search; the first run returns everything as new. limit/offset page the returned rows on this Worker; every call starts a new billed run, so fetch the pages you need from one result instead of re-calling. EXAMPLE: {"companies":["stripe.com","ramp.com"],"titleIncludes":["engineer"],"countries":["US"],"onlyNew":true}.

    Annotations the server declares

    • title: Search and monitor jobs across many companies (paid Apify Actor)
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: true

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Exfil surface

Which tools read private data, which read text someone else can write, and which can send data out. One of each is a path a prompt injection can use.

No private-data, untrusted-input, outbound path in this server alone: no tool is tagged private-data or outbound.

Reads private data0
Reads files, mail, messages, databases, secrets, calendars or repositories.
Reads text others write5
Brings in text someone else can write: web pages, inbound email, messages, issues and comments.
Can send data out0
Can carry data to people or systems: it sends, posts or publishes, or takes a recipient, channel or URL.

Other servers in the same agent add their own tools to these paths. Audit your whole setup to see them together.

Findings

Matches of fixed checks, with the text they matched.

1 warn5 info
  • The server marks "jobs_check_open" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

    Matched text

    annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}; The name "jobs_check_open" says "open": a word for a change.

    What this check looks for
  • The description is 2,476 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...gineer"],"remote":"only"} -> remote engineering roles at Ramp with salary ranges."

    What this check looks for
  • The description is 3,144 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...p.com"} -> [{"ats":"ashby","slug":"ramp","via":"seed_list","confidence":"high"}]."

    What this check looks for
  • The description is 2,117 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...ey":"greenhouse:stripe:8172503"} -> {"status":"open","method":"detail_endpoint"}."

    What this check looks for
  • The description is 2,658 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...emoved. EXAMPLE: {"jobKey":"greenhouse:stripe:8172503"} -> that Stripe job's row."

    What this check looks for
  • The description is 2,453 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...com","ramp.com"],"titleIncludes":["engineer"],"countries":["US"],"onlyNew":true}."

    What this check looks for

History

Changes to its tool definitions and to its remote endpoint, newest first.

No change seen yet. Its tools are rescanned every day, and a remote endpoint is looked at once a week.

Install

Pinned to version 1.1.9. Values in angle brackets are yours to fill in.

claude mcp add --transport http company-jobs-feed https://mcp.getfairquery.com/jobs/mcp
claude mcp add --transport http company-jobs-feed https://mcp.getfairquery.com/jobs/mcp

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change or a way out, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__company-jobs-feed__jobs_get_board",
      "mcp__company-jobs-feed__jobs_find_board",
      "mcp__company-jobs-feed__jobs_get_job",
      "mcp__company-jobs-feed__jobs_list_seed_boards",
      "mcp__company-jobs-feed__jobs_search_companies"
    ],
    "ask": [
      "mcp__company-jobs-feed__jobs_check_open"
    ],
    "deny": []
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. A read that can send data out (it takes a URL, say) asks first too. It assumes the server is installed as company-jobs-feed. Review it before you use it.

Capability tags behind 5 rules
  • mcp__company-jobs-feed__jobs_get_board untrusted-input
  • mcp__company-jobs-feed__jobs_find_board untrusted-input
  • mcp__company-jobs-feed__jobs_check_open untrusted-input
  • mcp__company-jobs-feed__jobs_get_job untrusted-input
  • mcp__company-jobs-feed__jobs_search_companies untrusted-input

Pin

Keep the decision: fail CI when the tools change, follow every change, or show a badge.

Pin in CI

Fail a build when the tools you reviewed are not the tools the server serves today.

curl -s "https://anlyon.dev/api/v1/servers/com.getfairquery/company-jobs-feed-mcp/verify?hash=6b0d238bcfccbe6296b5caef584f5a8ae7353ee15d920d65b37b0a5b99b52d20" | jq -e '.changed == false'

Pinned hash 6b0d238bcfcc, from Oct 27, 2026, 04:17 UTC.

Watch

Get told when its tools change: a new tool, a new description, a new class.

https://anlyon.dev/servers/com.getfairquery/company-jobs-feed-mcp/changes.xml

An Atom feed. Works in any feed reader or Slack's RSS app.

Badge

anlyon.dev badge for com.getfairquery/company-jobs-feed-mcp
[![anlyon.dev](https://anlyon.dev/badge/com.getfairquery/company-jobs-feed-mcp.svg)](https://anlyon.dev/servers/com.getfairquery/company-jobs-feed-mcp)

Source: MCP Registry. Synced Oct 27, 2026, 04:17 UTC.