# JobQuery > A single feed of job postings aggregated live from ~150 company ATS boards > (Greenhouse, Lever, Ashby, Gem, Workable, SmartRecruiters, Recruitee). Every > page view fans out to those boards and merges the results; nothing is stored, > so what you read is what the employers are publishing right now. There is a machine-shaped lane on purpose. Do not scrape the HTML — the same corpus is available as JSON and over MCP, and both are shaped by the same code that renders the pages, so they cannot disagree with what a reader sees. Two things to know before you call anything: - **Excerpt only.** No lane returns a full job description. Detail responses carry `description_excerpt`, the first 400 characters of the posting's text. The employer's board holds the full prose, and every result carries the canonical `url` to it. Send people there. - **Read `failed_boards`.** The feed is assembled from whichever boards answered. A response listing failed boards was built from fewer than the whole roster, and absence from such a feed is not evidence a role does not exist. The field is always present, and empty on a healthy feed. The feed narrows; it never ranks. There is no relevance ordering, no synonym expansion and no vector search — bring your own semantics, and probe with several narrow queries rather than expecting one to be interpreted. ## Machine-readable endpoints - [Feed as JSON](https://jobquery.io/jobs/list.json): one page of roles plus an envelope of `total`, `page`, `pages`, `per_page`, the `filters` actually applied, and `failed_boards`. Query params: `q` (keywords, ANDed, matched against title, company, department and location — not description), `location` (fuzzy string), `category` (closed vocabulary, see below), `remote` (`1` for remote-offered roles only), `page`, `per_page` (default 25, capped at 100). An unknown `category` is ignored and the whole feed returned, so compare `filters` in the envelope against what you asked for. - [One posting as JSON](https://jobquery.io/jobs/greenhouse/cloudflare/8158617.json): `/jobs/{vendor}/{board_token}/{id}.json` — the linked example is a live role and will 404 once it is filled. Addressed by the whole `(vendor, board_token, id)` triple, because ids are unique only within a board. The triple is on every search result. Supports conditional GET — `ETag` and `Last-Modified` are set, and the feed rebuilds at most every 10 minutes, so revalidate rather than re-download. - [Readiness](https://jobquery.io/up): 200 once the board registry loads and names at least one enabled board, 503 otherwise. A 503 means the app is misconfigured, not that hiring stopped. - MCP server at `https://jobquery.io/mcp` — described in full in the next section. Not linked, because it answers only POST. ## MCP `https://jobquery.io/mcp` speaks streamable HTTP: JSON-RPC over a single POST, no key, no account, no rate limit. GET and DELETE answer 405 with an `Allow: POST` header — that verb is the SSE half of the transport, and this server never initiates a message, so there is no stream to open. It announces itself as `jobquery` 1.1.0 and negotiates protocol `2025-06-18`. It publishes tools only: `prompts/list` and `resources/list` are both empty. Add it to any client that speaks remote MCP: ```json { "mcpServers": { "jobquery": { "type": "http", "url": "https://jobquery.io/mcp" } } } ``` In Claude Code: `claude mcp add --transport http jobquery https://jobquery.io/mcp` Three tools, all read-only, over the same corpus the JSON routes serve: - **`get_facets()`** — no arguments. Call it first. Returns `categories` (the closed 14-value vocabulary `search_jobs` will match on), `total_postings` and `uncategorized_postings` (currently 1,431 of 11,608 — about one role in eight maps to no category at all), `companies` (the enabled roster, each with `name`, `vendor`, `board_token`), `locations` (the 150 most common labels), `locations_truncated`, and `failed_boards`. - **`search_jobs(query?, location?, category?, remote?, page?, per_page?)`** — every argument optional; omit them all for the whole feed. `query` is keywords ANDed together, matched at word starts against title, company, department, employment and workplace type, and location labels — never against the description, which the feed does not carry. `category` must come from `get_facets`; anything else is silently ignored and the whole feed is returned. `location` is a fuzzy match on any string. `remote` narrows one way only. `per_page` defaults to 25 and is capped at 100. Returns the same envelope as `/jobs/list.json`, including the `filters` echo and `failed_boards`. - **`get_job(vendor, board_token, id)`** — all three required, as returned by `search_jobs`. Fetched live from the board rather than from the cached feed, so a filled or withdrawn role reports that instead of returning stale copy. Returns the structured fields plus `description_excerpt`. There is no parameter for more of the body. Every result carries the payload twice: `structuredContent` for a client that reads typed results, and the same JSON as a `content` text block for one that does not. A failure the calling model should act on comes back as `isError: true` with a sentence saying what happened — the four cases are kept apart on purpose, because they call for different responses: a posting that does not exist (filled or withdrawn, do not retry), a board rate-limiting the feed (retry shortly), a board that has been taken private (it will not come back), and a board that could not be reached (transient). A registry naming no enabled board is reported as server misconfiguration rather than as an empty result. ## Human-readable pages - [For agents](https://jobquery.io/for-agents): the integration reference for a developer wiring this feed into a client — the MCP endpoint, the three tool contracts, the JSON routes and both postures above, as a page. It says what this file says, rendered from the code rather than copied from it. - [Feed](https://jobquery.io/): the same corpus as HTML, with the same `q`, `location`, `category` and `remote` filters as query params. - [A posting](https://jobquery.io/jobs/greenhouse/cloudflare/8158617): excerpt, structured fields, and a link to apply on the employer's own board. ## Optional - [Categories](https://jobquery.io/jobs/list.json?category=engineering): a canonical vocabulary each board's own department label is mapped onto, retrieved from `get_facets`. It declines rather than guesses: about one posting in eight maps to nothing, carries no category, and is reachable only in the unfiltered feed. Filtering by category will not find those roles. - [Locations](https://jobquery.io/jobs/list.json?location=Berlin): a fuzzy match accepting any string, so the labels `get_facets` returns are examples of spelling, not a menu. - [Remote](https://jobquery.io/jobs/list.json?remote=1): narrows one way only. There is no on-site filter, because most boards never state a workplace type and the feed will not assert a negative no employer published.