{
  "markdown": "<img src=\"assets/icon-128.png\" alt=\"\" width=\"96\" align=\"right\">\n\n# mcp-lever\n\n[![npm](https://img.shields.io/npm/v/mcp-lever.svg)](https://www.npmjs.com/package/mcp-lever)\n[![CI](https://github.com/smeet666/mcp-lever/actions/workflows/ci.yml/badge.svg)](https://github.com/smeet666/mcp-lever/actions/workflows/ci.yml)\n[![license](https://img.shields.io/npm/l/mcp-lever.svg)](./LICENSE)\n[![MCP Registry](https://img.shields.io/badge/MCP_Registry-listed-6E56CF)](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.smeet666/mcp-lever)\n[![Glama](https://glama.ai/mcp/servers/smeet666/mcp-lever/badges/score.svg)](https://glama.ai/mcp/servers/smeet666/mcp-lever)\n[![M8ven](https://m8ven.ai/badge/mcp/smeet666-mcp-lever-ti7zmm?variant=verified)](https://m8ven.ai/mcp/smeet666-mcp-lever-ti7zmm)\n[![LobeHub](https://lobehub.com/badge/mcp/smeet666-mcp-lever)](https://lobehub.com/mcp/smeet666-mcp-lever)\n[![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=lever&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm1jcC1sZXZlciJdfQ%3D%3D)\n[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=lever&config=%7B%22name%22%3A%22lever%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22mcp-lever%22%5D%7D)\n\n<!-- m8ven-verify: 5faf86e7541e0167239ba83df2f3a7cc -->\n\n[Lever](https://www.lever.co) is recruiting software that thousands of companies\nuse to run their hiring, and every customer gets a public job board that comes\nwith it. Each board carries that company's open positions with their title,\ntheir location, the team and department they sit in, the commitment they ask for,\nthe full advert, and the salary range where the company chose to publish one.\nLever hosts one board per company, on either its global or its European instance,\nand publishes no index across them.\n\nThis server connects a chat client to those boards. You name the companies you\nare interested in, and it turns each name into the site name that addresses its\nboard, searches their openings, filters them by location, team, workplace type,\ncountry, salary or how recently they were posted, reads one opening in full, and\nlists the wordings each company filters by. It needs no API key and no account.\n\n_[Version française](#mcp-lever-français)_\n\n---\n\n## Install\n\n**One-click install**\n\n[![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=lever&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm1jcC1sZXZlciJdfQ%3D%3D)\n[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=lever&config=%7B%22name%22%3A%22lever%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22mcp-lever%22%5D%7D)\n\n**Claude Code**\n\n```bash\nclaude mcp add lever -- npx -y mcp-lever\n```\n\n**Claude Desktop, Cursor, and any client using the standard config format**\n\n```json\n{\n  \"mcpServers\": {\n    \"lever\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-lever\"]\n    }\n  }\n}\n```\n\nNode 24 or later is required, and no environment variable has to be set.\n\n### With Docker\n\n```json\n{\n  \"mcpServers\": {\n    \"lever\": {\n      \"command\": \"docker\",\n      \"args\": [\"run\", \"-i\", \"--rm\", \"ghcr.io/smeet666/mcp-lever:2.0.1\"]\n    }\n  }\n}\n```\n\n`-i` keeps stdin open, which is where the protocol travels, and `-t` is left out\nbecause a TTY rewrites the stream. The container needs outbound HTTPS to\n`api.lever.co` and `api.eu.lever.co`, and nothing else: no volume, no port, no\ncredential.\n\n### Bundle, without npm\n\nDownload `mcp-lever-2.0.1.mcpb` from\n[the latest release](https://github.com/smeet666/mcp-lever/releases/latest) and\nopen it. A client that supports MCP bundles installs it on its own, with no npm\nand no configuration file to edit. The bundle carries its dependencies, so\nnothing is fetched at install time.\n\n## What you can ask\n\n- \"Which of Included Health, Netlify and Ramp are hiring on Lever?\"\n- \"Find me remote engineering roles at those three companies.\"\n- \"Read me that opening in full.\"\n- \"What locations does Included Health list its jobs under?\"\n- \"Anything posted in the last two weeks at Netlify?\"\n\nEvery question starts from a company, since Lever offers no search across boards.\n`search_jobs` resolves the names you give it, so no preparation is needed:\n\n```\nresolve_company([\"Included Health\"])  ->  includedhealth, global instance, publishing\nsearch_jobs([\"Included Health\"], keyword: \"therapist\")\nget_job(\"includedhealth\", \"6f97a19f-…\")\n```\n\n## Tools\n\n| Tool                 | What it does                                                   |\n| -------------------- | -------------------------------------------------------------- |\n| `resolve_company`    | Turns company names into the Lever site names of their boards. |\n| `search_jobs`        | Searches the openings of the companies you name.               |\n| `get_job`            | Reads one opening in full, advert included.                    |\n| `list_filter_values` | Lists the wordings one company files its openings under.       |\n\nA Lever site name distinguishes case, so `Flex` answers where `flex` returns\nnothing. Four spellings are tried per name on each of the two instances, and the\nanswer lists what was sent, so nothing found is never proof that a company is\nabsent from Lever.\n\n### `resolve_company`\n\nTurns company names into Lever site names, reporting every instance that\nanswered. It takes a list.\n\n| Argument | Type                     | Required | What it does                                         |\n| -------- | ------------------------ | -------- | ---------------------------------------------------- |\n| `names`  | array of 1 to 25 strings | yes      | Company names, or Lever site names you already know. |\n\n**In return:** one entry per name, carrying `input`; `found`, a list of\n`{ slug, instance, publishes }` where `publishes` is false for a site that exists\nand lists nothing today; `tried`, the spellings sent in order; and `cached`, true\nwhen this session had already resolved that name. A name answering on both\ninstances comes back with both, and neither is elected: pass the one you mean to\nthe other tools.\n\n### `search_jobs`\n\nSearches the openings of the companies named. Lever applies the filters it\nsupports on its own exact wording, and this server applies the rest to the\nopenings it read.\n\n| Argument             | Type                              | Required | What it does                                                      |\n| -------------------- | --------------------------------- | -------- | ----------------------------------------------------------------- |\n| `companies`          | array of 1 to 25 strings          | yes      | Company names or Lever site names. Each is resolved here.         |\n| `keyword`            | string                            | no       | Words to look for in the title and the advert.                    |\n| `location`           | array of 1 to 20 strings          | no       | Locations, exactly as Lever writes them.                          |\n| `team`               | array of 1 to 20 strings          | no       | Teams, exactly as Lever writes them.                              |\n| `department`         | array of 1 to 20 strings          | no       | Departments, exactly as Lever writes them.                        |\n| `commitment`         | array of 1 to 20 strings          | no       | Commitments, exactly as Lever writes them.                        |\n| `workplace_type`     | array of 1 to 4 strings           | no       | `remote`, `hybrid`, `onsite` or `unspecified`.                    |\n| `country`            | array of 1 to 20 two-letter codes | no       | Countries as ISO codes, as in `FR` or `US`.                       |\n| `salary_min`         | number, 0 or more                 | no       | The lowest upper bound of a salary range to keep.                 |\n| `salary_interval`    | string                            | no       | The period `salary_min` is written in, such as `per-year-salary`. |\n| `currency`           | three-letter code                 | no       | The currency `salary_min` is written in, as in `EUR`.             |\n| `posted_within_days` | integer, 1 to 3650                | no       | How recent an opening must be.                                    |\n| `limit`              | integer, 1 to 100, default `25`   | no       | Openings to read per company.                                     |\n| `skip`               | integer, 0 to 100000, default `0` | no       | Openings to step over per company.                                |\n\nLever itself applies `location`, `team`, `department` and `commitment`; this\nserver applies `keyword`, `workplace_type`, `country`, `salary_min`,\n`salary_interval`, `currency` and `posted_within_days` to what it read.\n`list_filter_values` publishes the wordings the first four take, and a wording\nLever does not know comes back as an empty list.\n\n**In return:** `jobs`, each carrying `id` and `company_slug`, which `get_job`\ntakes, plus `title`, `location`, `all_locations`, `country`, `workplace_type`,\n`team`, `posted_at`, `url` and `apply_url`. `commitment` and `department` are\nabsent when the company records neither. `salary` is `null` for an opening\npublished without one, which is never the same as zero, and it carries the\n`interval` Lever wrote it in, never converted or annualised. `per_company` gives\none outcome per company, with a `status` of `read`, `unresolved`, `empty` or\n`failed`, which are four different answers, and the `read` and `returned` counts\naround the filters. `total_available` is always `null`: Lever publishes no result\ncount. The rows carry no advert text, since one company's board can run to\nmegabytes.\n\n`limit` applies per company, and a company whose openings fill it may publish\nmore: the notes say when that happened, and that a count taken inside that window\nmeasures the window. `posted_within_days` walks up to five pages per company,\nand Lever pages by title, so an opening published yesterday can sit anywhere in a\nboard.\n\n### `get_job`\n\nReads one opening in full: the advert, its named sections, and the salary as\npublished.\n\n| Argument       | Type             | Required | What it does                                               |\n| -------------- | ---------------- | -------- | ---------------------------------------------------------- |\n| `company_slug` | string           | yes      | The Lever site name, as `resolve_company` returns it.      |\n| `job_id`       | string           | yes      | The identifier of one opening, as a search returns it.     |\n| `instance`     | `global` or `eu` | no       | The instance the row came from. The global one by default. |\n\n**In return:** `job`, holding the fields a search row carries, plus\n`description`, `sections` as `{ heading, items }`, `salary_note` for what the\ncompany wrote beside the range, and `source` with the address it was retrieved\nfrom.\n\n### `list_filter_values`\n\nLists the team, location and commitment wordings one company uses. Read it before\nfiltering: Lever matches its own wording, and the vocabulary belongs to each\ncompany, one writing `Full-time` where another writes `EE Full-Time`.\n\n| Argument       | Type                                                | Required | What it does                                                                           |\n| -------------- | --------------------------------------------------- | -------- | -------------------------------------------------------------------------------------- |\n| `company_slug` | string                                              | yes      | The Lever site name, as `resolve_company` returns it.                                  |\n| `instance`     | `global` or `eu`                                    | no       | The instance this site lives on. The global one by default.                            |\n| `fields`       | array of 1 to 3 of `team`, `location`, `commitment` | no       | Which vocabularies to read. Each costs one request, and all three are read by default. |\n\n**In return:** `company_slug`, `instance`, and `fields` holding a list of\n`{ value, count }` for each vocabulary asked for. A `count` is `null` where Lever\npublished no figure alongside the category.\n\n## Configuration\n\nNothing has to be configured. The server reads no environment variable, and the\n`mcpServers` block above is complete as written.\n\nThe pacing, the timeout and the cache are settings of the client layer, which\n[As a library](#as-a-library) shows how to pass. The interval between two\nrequests can be widened there and never narrowed.\n\n## Errors\n\nEvery failure carries one of six codes, a message, and where it helps the values\nthat would have been accepted.\n\n| Code            | What happened                                           | What to do                                                                        |\n| --------------- | ------------------------------------------------------- | --------------------------------------------------------------------------------- |\n| `not_found`     | Lever answered, and holds no such site or opening.      | Check the site name with `resolve_company`.                                       |\n| `invalid_input` | The arguments were refused before any request went out. | Read the message, which names the argument and what it takes.                     |\n| `rate_limited`  | Lever asked this client to slow down.                   | Wait, then call again with the same arguments. The opening is still on the board. |\n| `parse_failure` | Lever answered in a shape this client cannot read.      | Report it at [the issue tracker](https://github.com/smeet666/mcp-lever/issues).   |\n| `network_error` | The request did not complete.                           | Try again shortly.                                                                |\n| `timeout`       | The request passed its deadline.                        | Ask for fewer companies, or a smaller `limit`.                                    |\n\n## As a library\n\nThe layer reading Lever is published on its own, with its pacing, its cache and\nits errors, and with no protocol attached.\n\n```ts\nimport { Client } from \"mcp-lever/client\";\n\nconst client = new Client({ minIntervalMs: 2000 });\nconst resolved = await client.resolveCompany(\"Included Health\");\nconst jobs = await client.listPostings(resolved.found[0], { limit: 10 });\nconsole.log(jobs.length);\n```\n\n`ClientOptions` takes `minIntervalMs`, `timeoutMs`, `cacheTtlMs` and `fetchImpl`.\nAn interval below the published floor is ignored, so the floor holds here as\nwell.\n\n## Pacing and attribution\n\nBoth API hosts publish `Crawl-delay: 1`, so requests go out one at a time with at\nleast a second between them, and that floor holds however the client is\nconfigured. The `User-Agent` carries the project and an address where a person\ncan be reached, and imitates no browser.\n\nReads go to `api.lever.co` and `api.eu.lever.co`, which are the hosts Lever\ndocuments for its posting data. The `jobs.lever.co` careers pages are left alone.\n\nEvery opening carries the address of its Lever page and its apply URL. Credit the\ncompany and link that page when you show an opening.\n\nThis MCP server is an unofficial project, with no affiliation to Lever or to the\ncompanies whose boards it reads.\n\n## Privacy\n\nThis server collects nothing about you and sends nothing to its author. It runs\non your machine, contacts `api.lever.co` and `api.eu.lever.co` and nothing else, holds its answers in memory\nwhile it runs, and writes nothing to disk.\n[PRIVACY.md](PRIVACY.md) states what a request carries and which settings change\nany of it.\n\n## Development\n\n```bash\nnpm install\nnpm run build:fixtures\nnpm test\nnpm run check\n```\n\nTests run against generated fixtures and make no network request. The live suite,\n`npm run test:live`, makes one request per route and runs nightly against the\nservice itself.\n\n## Contributing\n\nBugs, questions and ideas belong in\n[the issue tracker](https://github.com/smeet666/mcp-lever/issues). Pull requests\nare welcome; opening an issue first helps agree on the shape of the change. See\n[CONTRIBUTING.md](CONTRIBUTING.md).\n\n## License\n\nMIT, see [LICENSE](LICENSE). The openings belong to the companies that published\nthem.\n\n---\n\n<a name=\"mcp-lever-français\"></a>\n\n# mcp-lever (français)\n\n_[English version](#mcp-lever)_\n\n[Lever](https://www.lever.co) est un logiciel de recrutement qu'utilisent des\nmilliers d'entreprises pour mener leurs embauches, et chaque cliente reçoit avec\nlui un site d'offres public. Chaque site porte les postes ouverts de cette\nentreprise avec leur intitulé, leur lieu, l'équipe et le département auxquels ils\nappartiennent, le type de contrat demandé, l'annonce complète, et la fourchette\nde salaire quand l'entreprise a choisi d'en publier une. Lever héberge un site\npar entreprise, sur son instance mondiale ou sur son instance européenne, et ne\npublie aucun index les traversant.\n\nCe serveur relie un client de conversation à ces sites. Vous nommez les\nentreprises qui vous intéressent, et il traduit chaque nom en l'identifiant qui\nadresse son site, cherche dans leurs offres, les filtre par lieu, équipe, mode de\ntravail, pays, salaire ou fraîcheur de publication, lit une offre en entier, et\nliste les formulations selon lesquelles chaque entreprise classe les siennes.\nAucune clé d'API, aucun compte.\n\n## Installation\n\n**Installation en un clic**\n\n[![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=lever&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm1jcC1sZXZlciJdfQ%3D%3D)\n[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=lever&config=%7B%22name%22%3A%22lever%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22mcp-lever%22%5D%7D)\n\n**Claude Code**\n\n```bash\nclaude mcp add lever -- npx -y mcp-lever\n```\n\n**Claude Desktop, Cursor, et tout client au format de configuration standard**\n\n```json\n{\n  \"mcpServers\": {\n    \"lever\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-lever\"]\n    }\n  }\n}\n```\n\nNode 24 ou plus récent est nécessaire, et aucune variable d'environnement n'est à\nrenseigner.\n\n### Avec Docker\n\n```json\n{\n  \"mcpServers\": {\n    \"lever\": {\n      \"command\": \"docker\",\n      \"args\": [\"run\", \"-i\", \"--rm\", \"ghcr.io/smeet666/mcp-lever:2.0.1\"]\n    }\n  }\n}\n```\n\n`-i` garde l'entrée standard ouverte, qui est le canal du protocole, et `-t` est\nomis parce qu'un TTY réécrit le flux. Le conteneur a besoin d'un accès HTTPS\nsortant vers `api.lever.co` et `api.eu.lever.co`, et de rien d'autre : aucun\nvolume, aucun port, aucun identifiant.\n\n### Bundle, sans npm\n\nTéléchargez `mcp-lever-2.0.1.mcpb` depuis\n[la dernière publication](https://github.com/smeet666/mcp-lever/releases/latest)\net ouvrez-le. Un client qui gère les bundles MCP l'installe seul, sans npm et\nsans fichier de configuration à modifier. Le bundle emporte ses dépendances, donc\nrien n'est téléchargé à l'installation.\n\n## Ce qu'on peut demander\n\n- « Lesquelles d'Included Health, Netlify et Ramp recrutent sur Lever ? »\n- « Trouve-moi des postes d'ingénierie en télétravail chez ces trois-là. »\n- « Lis-moi cette offre en entier. »\n- « Sous quels lieux Included Health classe-t-elle ses offres ? »\n- « Quelque chose publié ces quinze derniers jours chez Netlify ? »\n\nChaque question part d'une entreprise, puisque Lever n'offre aucune recherche\ntraversant les sites. `search_jobs` résout lui-même les noms qu'on lui donne,\ndonc rien n'est à préparer :\n\n```\nresolve_company([\"Included Health\"])  ->  includedhealth, instance mondiale, publie\nsearch_jobs([\"Included Health\"], keyword: \"therapist\")\nget_job(\"includedhealth\", \"6f97a19f-…\")\n```\n\n## Les outils\n\n| Outil                | Ce qu'il fait                                                  |\n| -------------------- | -------------------------------------------------------------- |\n| `resolve_company`    | Traduit des noms d'entreprises en identifiants de sites Lever. |\n| `search_jobs`        | Cherche dans les offres des entreprises nommées.               |\n| `get_job`            | Lit une offre en entier, annonce comprise.                     |\n| `list_filter_values` | Liste les formulations sous lesquelles une entreprise classe.  |\n\nUn identifiant de site Lever distingue la casse, donc `Flex` répond là où `flex`\nne rend rien. Quatre orthographes sont essayées par nom sur chacune des deux\ninstances, et la réponse liste ce qui a été envoyé : ne rien trouver ne prouve\njamais qu'une entreprise est absente de Lever.\n\n### `resolve_company`\n\nTraduit des noms d'entreprises en identifiants de sites Lever, en signalant\nchaque instance qui a répondu. Il prend une liste.\n\n| Argument | Type                      | Requis | Ce qu'il fait                                            |\n| -------- | ------------------------- | ------ | -------------------------------------------------------- |\n| `names`  | tableau de 1 à 25 chaînes | oui    | Des noms d'entreprises, ou des identifiants déjà connus. |\n\n**En retour :** une entrée par nom, portant `input` ; `found`, une liste de\n`{ slug, instance, publishes }` où `publishes` est faux pour un site qui existe\net ne liste rien aujourd'hui ; `tried`, les orthographes envoyées dans l'ordre ;\net `cached`, vrai quand la session avait déjà résolu ce nom. Un nom qui répond\nsur les deux instances revient avec les deux, et aucune n'est élue : passez celle\nque vous visez aux autres outils.\n\n### `search_jobs`\n\nCherche dans les offres des entreprises nommées. Lever applique les filtres qu'il\ngère sur sa propre formulation exacte, et ce serveur applique les autres aux\noffres qu'il a lues.\n\n| Argument             | Type                                   | Requis | Ce qu'il fait                                                                   |\n| -------------------- | -------------------------------------- | ------ | ------------------------------------------------------------------------------- |\n| `companies`          | tableau de 1 à 25 chaînes              | oui    | Noms d'entreprises ou identifiants. Chacun est résolu ici.                      |\n| `keyword`            | chaîne                                 | non    | Mots à chercher dans l'intitulé et dans l'annonce.                              |\n| `location`           | tableau de 1 à 20 chaînes              | non    | Des lieux, exactement comme Lever les écrit.                                    |\n| `team`               | tableau de 1 à 20 chaînes              | non    | Des équipes, exactement comme Lever les écrit.                                  |\n| `department`         | tableau de 1 à 20 chaînes              | non    | Des départements, exactement comme Lever les écrit.                             |\n| `commitment`         | tableau de 1 à 20 chaînes              | non    | Des types de contrat, exactement comme Lever les écrit.                         |\n| `workplace_type`     | tableau de 1 à 4 chaînes               | non    | `remote`, `hybrid`, `onsite` ou `unspecified`.                                  |\n| `country`            | tableau de 1 à 20 codes à deux lettres | non    | Des pays en code ISO, comme `FR` ou `US`.                                       |\n| `salary_min`         | nombre, 0 ou plus                      | non    | La plus basse borne haute de fourchette à conserver.                            |\n| `salary_interval`    | chaîne                                 | non    | La période dans laquelle `salary_min` est écrit, par exemple `per-year-salary`. |\n| `currency`           | code à trois lettres                   | non    | La devise dans laquelle `salary_min` est écrit, comme `EUR`.                    |\n| `posted_within_days` | entier, 1 à 3650                       | non    | L'ancienneté maximale d'une offre.                                              |\n| `limit`              | entier, 1 à 100, défaut `25`           | non    | Offres à lire par entreprise.                                                   |\n| `skip`               | entier, 0 à 100000, défaut `0`         | non    | Offres à enjamber par entreprise.                                               |\n\nLever applique lui-même `location`, `team`, `department` et `commitment` ; ce\nserveur applique `keyword`, `workplace_type`, `country`, `salary_min`,\n`salary_interval`, `currency` et `posted_within_days` à ce qu'il a lu.\n`list_filter_values` publie les formulations que prennent les quatre premiers, et\nune formulation que Lever ignore revient en liste vide.\n\n**En retour :** `jobs`, chacune portant `id` et `company_slug`, que `get_job`\nreprend, plus `title`, `location`, `all_locations`, `country`, `workplace_type`,\n`team`, `posted_at`, `url` et `apply_url`. `commitment` et `department` sont\nabsents quand l'entreprise ne les renseigne pas. `salary` vaut `null` pour une\noffre publiée sans fourchette, ce qui ne vaut jamais zéro, et porte l'`interval`\ndans lequel Lever l'a écrite, jamais converti ni annualisé. `per_company` donne\nune issue par entreprise, avec un `status` valant `read`, `unresolved`, `empty`\nou `failed`, qui sont quatre réponses différentes, et les comptes `read` et\n`returned` de part et d'autre des filtres. `total_available` vaut toujours\n`null` : Lever ne publie aucun compte de résultats. Les lignes ne portent pas\nl'annonce, un site d'entreprise pouvant peser plusieurs mégaoctets.\n\n`limit` s'applique par entreprise, et une entreprise dont les offres le\nremplissent en publie peut-être davantage : les notes le signalent, et disent\nqu'un compte pris dans cette fenêtre mesure la fenêtre. `posted_within_days`\nparcourt jusqu'à cinq pages par entreprise, et Lever pagine par intitulé, donc\nune offre publiée hier peut se trouver n'importe où dans un site.\n\n### `get_job`\n\nLit une offre en entier : l'annonce, ses sections nommées, et le salaire tel que\npublié.\n\n| Argument       | Type             | Requis | Ce qu'il fait                                           |\n| -------------- | ---------------- | ------ | ------------------------------------------------------- |\n| `company_slug` | chaîne           | oui    | L'identifiant du site, rendu par `resolve_company`.     |\n| `job_id`       | chaîne           | oui    | L'identifiant d'une offre, rendu par une recherche.     |\n| `instance`     | `global` ou `eu` | non    | L'instance d'où vient la ligne. La mondiale par défaut. |\n\n**En retour :** `job`, qui porte les champs d'une ligne de recherche, plus\n`description`, `sections` en `{ heading, items }`, `salary_note` pour ce que\nl'entreprise a écrit à côté de la fourchette, et `source` avec l'adresse d'où\nl'offre a été lue.\n\n### `list_filter_values`\n\nListe les formulations d'équipe, de lieu et de contrat qu'une entreprise emploie.\nÀ lire avant de filtrer : Lever fait correspondre sa propre formulation, et le\nvocabulaire appartient à chaque entreprise, l'une écrivant `Full-time` là où une\nautre écrit `EE Full-Time`.\n\n| Argument       | Type                                                    | Requis | Ce qu'il fait                                                                        |\n| -------------- | ------------------------------------------------------- | ------ | ------------------------------------------------------------------------------------ |\n| `company_slug` | chaîne                                                  | oui    | L'identifiant du site, rendu par `resolve_company`.                                  |\n| `instance`     | `global` ou `eu`                                        | non    | L'instance où vit ce site. La mondiale par défaut.                                   |\n| `fields`       | tableau de 1 à 3 parmi `team`, `location`, `commitment` | non    | Les vocabulaires à lire. Chacun coûte une requête, et les trois sont lus par défaut. |\n\n**En retour :** `company_slug`, `instance`, et `fields` qui porte une liste de\n`{ value, count }` pour chaque vocabulaire demandé. Un `count` vaut `null`\nlà où Lever n'a publié aucun chiffre à côté de la catégorie.\n\n## Configuration\n\nIl n'y a rien à configurer. Le serveur ne lit aucune variable d'environnement, et\nle bloc `mcpServers` ci-dessus est complet tel quel.\n\nLe rythme, le délai et le cache sont des réglages de la couche cliente, que\n[Comme bibliothèque](#comme-bibliothèque) montre comment passer. L'écart entre\ndeux requêtes peut y être élargi et jamais resserré.\n\n## Erreurs\n\nChaque échec porte un des six codes, un message, et quand cela aide les valeurs\nqui auraient été acceptées.\n\n| Code            | Ce qui s'est passé                                       | Que faire                                                                             |\n| --------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------- |\n| `not_found`     | Lever a répondu, et n'a ni ce site ni cette offre.       | Vérifiez l'identifiant avec `resolve_company`.                                        |\n| `invalid_input` | Les arguments ont été refusés avant toute requête.       | Lisez le message, qui nomme l'argument et ce qu'il prend.                             |\n| `rate_limited`  | Lever demande à ce client de ralentir.                   | Attendez, puis rappelez avec les mêmes arguments. L'offre est toujours en ligne.      |\n| `parse_failure` | Lever a répondu dans une forme que ce client ne lit pas. | Signalez-le sur [le suivi d'incidents](https://github.com/smeet666/mcp-lever/issues). |\n| `network_error` | La requête n'a pas abouti.                               | Réessayez sous peu.                                                                   |\n| `timeout`       | La requête a dépassé son délai.                          | Demandez moins d'entreprises, ou un `limit` plus petit.                               |\n\n## Comme bibliothèque\n\nLa couche qui lit Lever est publiée seule, avec son rythme, son cache et ses\nerreurs, sans protocole attaché.\n\n```ts\nimport { Client } from \"mcp-lever/client\";\n\nconst client = new Client({ minIntervalMs: 2000 });\nconst resolved = await client.resolveCompany(\"Included Health\");\nconst jobs = await client.listPostings(resolved.found[0], { limit: 10 });\nconsole.log(jobs.length);\n```\n\n`ClientOptions` prend `minIntervalMs`, `timeoutMs`, `cacheTtlMs` et `fetchImpl`.\nUn écart sous le plancher publié est ignoré, donc le plancher tient également\nici.\n\n## Rythme et attribution\n\nLes deux hôtes d'API publient `Crawl-delay: 1`, donc les requêtes partent une à\nune avec au moins une seconde entre elles, et ce plancher tient quelle que soit\nla configuration du client. Le `User-Agent` porte le projet et une adresse où\njoindre une personne, et n'imite aucun navigateur.\n\nLes lectures vont vers `api.lever.co` et `api.eu.lever.co`, les hôtes que Lever\ndocumente pour ses données d'offres. Les pages carrières `jobs.lever.co` sont\nlaissées tranquilles.\n\nChaque offre porte l'adresse de sa page Lever et son adresse de candidature.\nCréditez l'entreprise et renvoyez vers cette page quand vous montrez une offre.\n\nCe MCP est un projet non officiel, sans affiliation à Lever ni aux entreprises\ndont il lit les sites.\n\n## Confidentialité\n\nCe serveur ne collecte rien sur vous et n'envoie rien à son auteur. Il tourne sur\nvotre machine, ne joint que `api.lever.co` et `api.eu.lever.co`, garde ses réponses en mémoire le temps qu'il\ntourne, et n'écrit rien sur le disque. [PRIVACY.md](PRIVACY.md) dit ce qu'une\nrequête emporte et quels réglages changent cela.\n\n## Développement\n\n```bash\nnpm install\nnpm run build:fixtures\nnpm test\nnpm run check\n```\n\nLes tests s'exécutent sur des fixtures engendrées et n'émettent aucune requête.\nLa suite en direct, `npm run test:live`, émet une requête par route et tourne\nchaque nuit contre le service lui-même.\n\n## Contribuer\n\nLes anomalies, les questions et les idées ont leur place dans\n[le suivi d'incidents](https://github.com/smeet666/mcp-lever/issues). Les\npropositions de modification sont bienvenues ; ouvrir un ticket d'abord aide à\ns'accorder sur la forme du changement. Voir [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Licence\n\nMIT, voir [LICENSE](LICENSE). Les offres appartiennent aux entreprises qui les\nont publiées.\n",
  "bytes": 32525,
  "sha": "defbfe86d116313e973c2823d501f8d42eaca878c4abe4f868386b0dbecece83",
  "repo_slug": "smeet666/mcp-lever",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_smeet666_mcp_lever_88617310/readme"
}