Lever job boards
Busca en bolsas de trabajo públicas de Lever: resuelve una empresa, lee sus vacantes, lee una completa.
Documentación
mcp-lever
Lever es un software de reclutamiento que miles de empresas utilizan para gestionar su contratación, y cada cliente recibe un tablón de empleo público que viene incluido. Cada tablón muestra las posiciones abiertas de esa empresa con su título, su ubicación, el equipo y departamento al que pertenecen, el tipo de compromiso que solicitan, el anuncio completo y el rango salarial cuando la empresa decide publicarlo. Lever aloja un tablón por empresa, ya sea en su instancia global o en su instancia europea, y no publica un índice que los abarque a todos.
Este servidor conecta un cliente de chat con esos tablones. Tú nombras las empresas que te interesan, y él convierte cada nombre en el nombre de sitio que dirige a su tablón, busca sus vacantes, las filtra por ubicación, equipo, tipo de lugar de trabajo, país, salario o por lo recientes que sean, lee una vacante completa y lista las palabras clave por las que cada empresa filtra. No necesita clave API ni cuenta.
Instalación
Instalación en un clic
Claude Code
claude mcp add lever -- npx -y mcp-lever
Claude Desktop, Cursor y cualquier cliente que use el formato de configuración estándar
{
"mcpServers": {
"lever": {
"command": "npx",
"args": ["-y", "mcp-lever"]
}
}
}
Se requiere Node 24 o posterior, y no es necesario establecer ninguna variable de entorno.
Con Docker
{
"mcpServers": {
"lever": {
"command": "docker",
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-lever:2.0.1"]
}
}
}
-i mantiene stdin abierto, que es por donde viaja el protocolo, y -t se omite
porque un TTY reescribe el flujo. El contenedor necesita HTTPS saliente hacia
api.lever.co y api.eu.lever.co, y nada más: sin volumen, sin puerto, sin
credencial.
Paquete, sin npm
Descarga mcp-lever-2.0.1.mcpb desde
la última versión y
ábrelo. Un cliente que admita paquetes MCP lo instala por sí solo, sin npm
y sin archivo de configuración que editar. El paquete incluye sus dependencias, por lo que
no se descarga nada en el momento de la instalación.
Lo que puedes preguntar
- "¿Cuáles de Included Health, Netlify y Ramp están contratando en Lever?"
- "Encuéntrame puestos remotos de ingeniería en esas tres empresas."
- "Léeme esa vacante completa."
- "¿Bajo qué ubicaciones lista Included Health sus empleos?"
- "¿Algo publicado en las últimas dos semanas en Netlify?"
Toda pregunta parte de una empresa, ya que Lever no ofrece búsqueda entre tablones.
search_jobs resuelve los nombres que le das, por lo que no se necesita preparación:
resolve_company(["Included Health"]) -> includedhealth, global instance, publishing
search_jobs(["Included Health"], keyword: "therapist")
get_job("includedhealth", "6f97a19f-…")
Herramientas
| Herramienta | Qué hace |
|---|---|
resolve_company | Convierte nombres de empresas en los nombres de sitio de Lever de sus tablones. |
search_jobs | Busca las vacantes de las empresas que nombras. |
get_job | Lee una vacante completa, incluido el anuncio. |
list_filter_values | Lista las palabras clave bajo las que una empresa archiva sus vacantes. |
Un nombre de sitio de Lever distingue mayúsculas, por lo que Flex responde donde flex no devuelve
nada. Se prueban cuatro grafías por nombre en cada una de las dos instancias, y la
respuesta lista lo que se envió, por lo que no encontrar nada nunca es prueba de que una empresa esté
ausente de Lever.
resolve_company
Convierte nombres de empresas en nombres de sitio de Lever, informando de cada instancia que respondió. Toma una lista.
| Argumento | Tipo | Obligatorio | Qué hace |
|---|---|---|---|
names | array de 1 a 25 cadenas | sí | Nombres de empresas, o nombres de sitio de Lever que ya conozcas. |
A cambio: una entrada por nombre, que lleva input; found, una lista de
{ slug, instance, publishes } donde publishes es falso para un sitio que existe
y no lista nada hoy; tried, las grafías enviadas en orden; y cached, verdadero
cuando esta sesión ya había resuelto ese nombre. Un nombre que responda en ambas
instancias vuelve con ambas, y ninguna es elegida: pasa la que quieras decir a las
otras herramientas.
search_jobs
Busca las vacantes de las empresas nombradas. Lever aplica los filtros que admite sobre su propia redacción exacta, y este servidor aplica el resto a las vacantes que leyó.
| Argumento | Tipo | Obligatorio | Qué hace |
|---|---|---|---|
companies | array de 1 a 25 cadenas | sí | Nombres de empresas o nombres de sitio de Lever. Cada uno se resuelve aquí. |
keyword | cadena | no | Palabras para buscar en el título y en el anuncio. |
location | array de 1 a 20 cadenas | no | Ubicaciones, exactamente como las escribe Lever. |
team | array de 1 a 20 cadenas | no | Equipos, exactamente como los escribe Lever. |
department | array de 1 a 20 cadenas | no | Departamentos, exactamente como los escribe Lever. |
commitment | array de 1 a 20 cadenas | no | Compromisos, exactamente como los escribe Lever. |
workplace_type | array de 1 a 4 cadenas | no | remote, hybrid, onsite o unspecified. |
country | array de 1 a 20 códigos de dos letras | no | Países como códigos ISO, como en FR o US. |
salary_min | número, 0 o más | no | El límite superior más bajo de un rango salarial a conservar. |
salary_interval | cadena | no | El período en el que está escrito salary_min, como per-year-salary. |
currency | código de tres letras | no | La moneda en la que está escrito salary_min, como en EUR. |
posted_within_days | entero, 1 a 3650 | no | Cuán reciente debe ser una vacante. |
limit | entero, 1 a 100, predeterminado 25 | no | Vacantes a leer por empresa. |
skip | entero, 0 a 100000, predeterminado 0 | no | Vacantes a omitir por empresa. |
Lever mismo aplica location, team, department y commitment; este
servidor aplica keyword, workplace_type, country, salary_min,
salary_interval, currency y posted_within_days a lo que leyó.
list_filter_values publica las palabras clave que toman los primeros cuatro, y una palabra clave
que Lever no conozca vuelve como una lista vacía.
A cambio: jobs, cada una llevando id y company_slug, que get_job
toma, además de title, location, all_locations, country, workplace_type,
team, posted_at, url y apply_url. commitment y department están
ausentes cuando la empresa no registra ninguno. salary es null para una vacante
publicada sin uno, que nunca es lo mismo que cero, y lleva la
interval en la que Lever lo escribió, nunca convertida ni anualizada. per_company da
un resultado por empresa, con un status de read, unresolved, empty o
failed, que son cuatro respuestas diferentes, y los conteos de read y returned
alrededor de los filtros. total_available es siempre null: Lever no publica ningún conteo
de resultados. Las filas no llevan texto de anuncio, ya que el tablón de una sola empresa puede alcanzar
megabytes.
limit se aplica por empresa, y una empresa cuyas vacantes lo llenen puede publicar
más: las notas dicen cuándo ocurrió eso, y que un conteo tomado dentro de esa ventana
mide la ventana. posted_within_days recorre hasta cinco páginas por empresa,
y Lever pagina por título, por lo que una vacante publicada ayer puede estar en cualquier lugar de un
tablón.
get_job
Lee una vacante completa: el anuncio, sus secciones nombradas y el salario tal como se publicó.
| Argumento | Tipo | Obligatorio | Qué hace |
|---|---|---|---|
company_slug | cadena | sí | El nombre de sitio de Lever, tal como lo devuelve resolve_company. |
job_id | cadena | sí | El identificador de una vacante, tal como lo devuelve una búsqueda. |
instance | global o eu | no | La instancia de la que proviene la fila. La global por defecto. |
A cambio: job, que contiene los campos que lleva una fila de búsqueda, además de
description, sections como { heading, items }, salary_note para lo que la
empresa escribió junto al rango, y source con la dirección de la que se recuperó.
list_filter_values
Lista las palabras clave de equipo, ubicación y compromiso que usa una empresa. Léelo antes de
filtrar: Lever coincide con su propia redacción, y el vocabulario pertenece a cada
empresa, una escribe Full-time donde otra escribe EE Full-Time.
| Argumento | Tipo | Obligatorio | Qué hace |
|---|---|---|---|
company_slug | cadena | sí | El nombre de sitio de Lever, tal como lo devuelve resolve_company. |
instance | global o eu | no | La instancia en la que vive este sitio. La global por defecto. |
fields | array de 1 a 3 de team, location, commitment | no | Qué vocabularios leer. Cada uno cuesta una solicitud, y los tres se leen por defecto. |
A cambio: company_slug, instance y fields que contienen una lista de
{ value, count } para cada vocabulario solicitado. Un count es null donde Lever
no publicó ninguna cifra junto a la categoría.
Configuración
No hay nada que configurar. El servidor no lee ninguna variable de entorno, y el
bloque mcpServers anterior está completo tal como está escrito.
El ritmo, el tiempo de espera y la caché son ajustes de la capa del cliente, que Como biblioteca muestra cómo pasar. El intervalo entre dos solicitudes se puede ampliar allí y nunca reducir.
Errores
Cada fallo lleva uno de seis códigos, un mensaje y, cuando ayuda, los valores que habrían sido aceptados.
| Código | Qué ocurrió | Qué hacer |
|---|---|---|
not_found | Lever respondió y no tiene ese sitio ni esa oferta. | Verifica el nombre del sitio con resolve_company. |
invalid_input | Los argumentos fueron rechazados antes de enviar cualquier solicitud. | Lee el mensaje, que indica el argumento y qué requiere. |
rate_limited | Lever pidió a este cliente que reduzca la velocidad. | Espera y vuelve a llamar con los mismos argumentos. La oferta sigue en el tablón. |
parse_failure | Lever respondió en un formato que este cliente no puede leer. | Repórtalo en el rastreador de incidencias. |
network_error | La solicitud no se completó. | Inténtalo de nuevo en breve. |
timeout | La solicitud superó su plazo. | Pide menos empresas o un limit más pequeño. |
Como biblioteca
La capa que lee Lever se publica por separado, con su propio ritmo, su caché y sus errores, y sin ningún protocolo adjunto.
import { Client } from "mcp-lever/client";
const client = new Client({ minIntervalMs: 2000 });
const resolved = await client.resolveCompany("Included Health");
const jobs = await client.listPostings(resolved.found[0], { limit: 10 });
console.log(jobs.length);
ClientOptions toma minIntervalMs, timeoutMs, cacheTtlMs y fetchImpl.
Un intervalo por debajo del mínimo publicado se ignora, por lo que el mínimo se mantiene aquí
también.
Ritmo y atribución
Ambos hosts de API publican Crawl-delay: 1, por lo que las solicitudes salen de una en una con al
menos un segundo entre ellas, y ese mínimo se mantiene sin importar cómo esté
configurado el cliente. El User-Agent lleva el proyecto y una dirección donde se puede
contactar a una persona, y no imita a ningún navegador.
Las lecturas van a api.lever.co y api.eu.lever.co, que son los hosts que Lever
documenta para sus datos de publicación. Las páginas de carreras de jobs.lever.co se dejan intactas.
Cada oferta lleva la dirección de su página de Lever y su URL de postulación. Da crédito a la empresa y enlaza esa página cuando muestres una oferta.
Este servidor MCP es un proyecto no oficial, sin afiliación con Lever ni con las empresas cuyos tablones lee.
Privacidad
Este servidor no recopila nada sobre ti y no envía nada a su autor. Se ejecuta
en tu máquina, contacta a api.lever.co y api.eu.lever.co y nada más, guarda sus respuestas en memoria
mientras se ejecuta y no escribe nada en el disco.
PRIVACY.md indica qué lleva una solicitud y qué ajustes cambian
cualquier parte de ello.
Desarrollo
npm install
npm run build:fixtures
npm test
npm run check
Las pruebas se ejecutan contra fixtures generados y no hacen ninguna solicitud de red. La suite en vivo,
npm run test:live, hace una solicitud por ruta y se ejecuta cada noche contra el
propio servicio.
Contribuciones
Errores, preguntas e ideas van en el rastreador de incidencias. Las solicitudes de extracción son bienvenidas; abrir una incidencia primero ayuda a acordar la forma del cambio. Consulta CONTRIBUTING.md.
Licencia
MIT, consulta LICENSE. Las ofertas pertenecen a las empresas que las publicaron.
mcp-lever (francés)
Lever es un software de reclutamiento que usan miles de empresas para llevar a cabo sus contrataciones, y cada cliente recibe con él un sitio de ofertas público. Cada sitio muestra los puestos abiertos de esa empresa con su título, ubicación, equipo y departamento al que pertenecen, el tipo de contrato solicitado, el anuncio completo y el rango salarial cuando la empresa ha elegido publicar uno. Lever aloja un sitio por empresa, en su instancia global o en su instancia europea, y no publica ningún índice que los atraviese.
Este servidor conecta un cliente de conversación con estos sitios. Nombras las empresas que te interesan, y él traduce cada nombre al identificador que direcciona su sitio, busca en sus ofertas, las filtra por ubicación, equipo, modalidad de trabajo, país, salario o frescura de publicación, lee una oferta completa y lista las formulaciones según las cuales cada empresa clasifica las suyas. Sin clave de API, sin cuenta.
Instalación
Instalación en un clic
Claude Code
claude mcp add lever -- npx -y mcp-lever
Claude Desktop, Cursor y cualquier cliente con formato de configuración estándar
{
"mcpServers": {
"lever": {
"command": "npx",
"args": ["-y", "mcp-lever"]
}
}
}
Se requiere Node 24 o más reciente, y no hay ninguna variable de entorno que completar.
Con Docker
{
"mcpServers": {
"lever": {
"command": "docker",
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-lever:2.0.1"]
}
}
}
-i mantiene la entrada estándar abierta, que es el canal del protocolo, y -t se
omite porque un TTY reescribe el flujo. El contenedor necesita acceso HTTPS
saliente a api.lever.co y api.eu.lever.co, y nada más: ningún
volumen, ningún puerto, ningún identificador.
Bundle, sin npm
Descarga mcp-lever-2.0.1.mcpb desde
la última publicación
y ábrelo. Un cliente que gestiona bundles MCP lo instala solo, sin npm y
sin archivo de configuración que modificar. El bundle incluye sus dependencias, por lo que
nada se descarga en la instalación.
Lo que se puede pedir
- «¿Cuáles de Included Health, Netlify y Ramp reclutan en Lever?»
- «Encuéntrame puestos de ingeniería en remoto en estos tres.»
- «Léeme esta oferta completa.»
- «¿Bajo qué ubicaciones clasifica Included Health sus ofertas?»
- «¿Algo publicado en los últimos quince días en Netlify?»
Cada pregunta parte de una empresa, ya que Lever no ofrece ninguna búsqueda
que atraviese los sitios. search_jobs resuelve por sí mismo los nombres que se le dan,
por lo que no hay nada que preparar:
resolve_company(["Included Health"]) -> includedhealth, instance mondiale, publie
search_jobs(["Included Health"], keyword: "therapist")
get_job("includedhealth", "6f97a19f-…")
Las herramientas
| Herramienta | Qué hace |
|---|---|
resolve_company | Traduce nombres de empresas a identificadores de sitios Lever. |
search_jobs | Busca en las ofertas de las empresas nombradas. |
get_job | Lee una oferta completa, anuncio incluido. |
list_filter_values | Lista las formulaciones bajo las cuales una empresa clasifica. |
Un identificador de sitio Lever distingue mayúsculas y minúsculas, por lo que Flex responde donde flex
no devuelve nada. Se prueban cuatro ortografías por nombre en cada una de las dos
instancias, y la respuesta lista lo que se envió: no encontrar nada nunca
prueba que una empresa esté ausente de Lever.
resolve_company
Traduce nombres de empresas a identificadores de sitios Lever, indicando cada instancia que respondió. Toma una lista.
| Argumento | Tipo | Requerido | Qué hace |
|---|---|---|---|
names | matriz de 1 a 25 cadenas | sí | Nombres de empresas, o identificadores ya conocidos. |
A cambio: una entrada por nombre, que lleva input ; found, una lista de
{ slug, instance, publishes } donde publishes es falso para un sitio que existe
y no lista nada hoy ; tried, las ortografías enviadas en orden ;
y cached, verdadero cuando la sesión ya había resuelto ese nombre. Un nombre que responde
en ambas instancias regresa con ambas, y ninguna es elegida: pasa la que
apuntes a las otras herramientas.
search_jobs
Busca en las ofertas de las empresas nombradas. Lever aplica los filtros que gestiona sobre su propia formulación exacta, y este servidor aplica los demás a las ofertas que ha leído.
| Argumento | Tipo | Requerido | Qué hace |
|---|---|---|---|
companies | matriz de 1 a 25 cadenas | sí | Nombres de empresas o identificadores. Cada uno se resuelve aquí. |
keyword | cadena | no | Palabras para buscar en el título y en el anuncio. |
location | matriz de 1 a 20 cadenas | no | Ubicaciones, exactamente como Lever las escribe. |
team | matriz de 1 a 20 cadenas | no | Equipos, exactamente como Lever los escribe. |
department | matriz de 1 a 20 cadenas | no | Departamentos, exactamente como Lever los escribe. |
commitment | matriz de 1 a 20 cadenas | no | Tipos de contrato, exactamente como Lever los escribe. |
workplace_type | matriz de 1 a 4 cadenas | no | remote, hybrid, onsite o unspecified. |
country | matriz de 1 a 20 códigos de dos letras | no | Países en código ISO, como FR o US. |
salary_min | número, 0 o más | no | El límite inferior más bajo del rango a conservar. |
salary_interval | cadena | no | El período en el que salary_min está escrito, por ejemplo per-year-salary. |
currency | código de tres letras | no | La moneda en la que salary_min está escrito, como EUR. |
posted_within_days | entero, 1 a 3650 | no | La antigüedad máxima de una oferta. |
limit | entero, 1 a 100, predeterminado 25 | no | Ofertas a leer por empresa. |
skip | entero, 0 a 100000, predeterminado 0 | no | Ofertas a omitir por empresa. |
Lever aplica por sí mismo location, team, department y commitment ; este
servidor aplica keyword, workplace_type, country, salary_min,
salary_interval, currency y posted_within_days a lo que ha leído.
list_filter_values publica las formulaciones que toman los primeros cuatro, y
una formulación que Lever ignora regresa en lista vacía.
En retour : jobs, chacune portant id et company_slug, que get_job
reprend, plus title, location, all_locations, country, workplace_type,
team, posted_at, url et apply_url. commitment et department sont
absents quand l'entreprise ne les renseigne pas. salary vaut null pour une
offre publiée sans fourchette, ce qui ne vaut jamais zéro, et porte l'interval
dans lequel Lever l'a écrite, jamais converti ni annualisé. per_company donne
une issue par entreprise, avec un status valant read, unresolved, empty
ou failed, qui sont quatre réponses différentes, et les comptes read et
returned de part et d'autre des filtres. total_available vaut toujours
null : Lever ne publie aucun compte de résultats. Les lignes ne portent pas
l'annonce, un site d'entreprise pouvant peser plusieurs mégaoctets.
limit s'applique par entreprise, et une entreprise dont les offres le
remplissent en publie peut-être davantage : les notes le signalent, et disent
qu'un compte pris dans cette fenêtre mesure la fenêtre. posted_within_days
parcourt jusqu'à cinq pages par entreprise, et Lever pagine par intitulé, donc
une offre publiée hier peut se trouver n'importe où dans un site.
get_job
Lit une offre en entier : l'annonce, ses sections nommées, et le salaire tel que publié.
| Argument | Type | Requis | Ce qu'il fait |
|---|---|---|---|
company_slug | chaîne | oui | L'identifiant du site, rendu par resolve_company. |
job_id | chaîne | oui | L'identifiant d'une offre, rendu par une recherche. |
instance | global ou eu | non | L'instance d'où vient la ligne. La mondiale par défaut. |
En retour : job, qui porte les champs d'une ligne de recherche, plus
description, sections en { heading, items }, salary_note pour ce que
l'entreprise a écrit à côté de la fourchette, et source avec l'adresse d'où
l'offre a été lue.
list_filter_values
Liste les formulations d'équipe, de lieu et de contrat qu'une entreprise emploie.
À lire avant de filtrer : Lever fait correspondre sa propre formulation, et le
vocabulaire appartient à chaque entreprise, l'une écrivant Full-time là où une
autre écrit EE Full-Time.
| Argument | Type | Requis | Ce qu'il fait |
|---|---|---|---|
company_slug | chaîne | oui | L'identifiant du site, rendu par resolve_company. |
instance | global ou eu | non | L'instance où vit ce site. La mondiale par défaut. |
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. |
En retour : company_slug, instance, et fields qui porte une liste de
{ value, count } pour chaque vocabulaire demandé. Un count vaut null
là où Lever n'a publié aucun chiffre à côté de la catégorie.
Configuration
Il n'y a rien à configurer. Le serveur ne lit aucune variable d'environnement, et
le bloc mcpServers ci-dessus est complet tel quel.
Le rythme, le délai et le cache sont des réglages de la couche cliente, que Comme bibliothèque montre comment passer. L'écart entre deux requêtes peut y être élargi et jamais resserré.
Erreurs
Chaque échec porte un des six codes, un message, et quand cela aide les valeurs qui auraient été acceptées.
| Code | Ce qui s'est passé | Que faire |
|---|---|---|
not_found | Lever a répondu, et n'a ni ce site ni cette offre. | Vérifiez l'identifiant avec resolve_company. |
invalid_input | Les arguments ont été refusés avant toute requête. | Lisez le message, qui nomme l'argument et ce qu'il prend. |
rate_limited | Lever demande à ce client de ralentir. | Attendez, puis rappelez avec les mêmes arguments. L'offre est toujours en ligne. |
parse_failure | Lever a répondu dans une forme que ce client ne lit pas. | Signalez-le sur le suivi d'incidents. |
network_error | La requête n'a pas abouti. | Réessayez sous peu. |
timeout | La requête a dépassé son délai. | Demandez moins d'entreprises, ou un limit plus petit. |
Comme bibliothèque
La couche qui lit Lever est publiée seule, avec son rythme, son cache et ses erreurs, sans protocole attaché.
import { Client } from "mcp-lever/client";
const client = new Client({ minIntervalMs: 2000 });
const resolved = await client.resolveCompany("Included Health");
const jobs = await client.listPostings(resolved.found[0], { limit: 10 });
console.log(jobs.length);
ClientOptions prend minIntervalMs, timeoutMs, cacheTtlMs et fetchImpl.
Un écart sous le plancher publié est ignoré, donc le plancher tient également
ici.
Rythme et attribution
Les deux hôtes d'API publient Crawl-delay: 1, donc les requêtes partent une à
une avec au moins une seconde entre elles, et ce plancher tient quelle que soit
la configuration du client. Le User-Agent porte le projet et une adresse où
joindre une personne, et n'imite aucun navigateur.
Les lectures vont vers api.lever.co et api.eu.lever.co, les hôtes que Lever
documente pour ses données d'offres. Les pages carrières jobs.lever.co sont
laissées tranquilles.
Chaque offre porte l'adresse de sa page Lever et son adresse de candidature. Créditez l'entreprise et renvoyez vers cette page quand vous montrez une offre.
Ce MCP est un projet non officiel, sans affiliation à Lever ni aux entreprises dont il lit les sites.
Confidentialité
Ce serveur ne collecte rien sur vous et n'envoie rien à son auteur. Il tourne sur
votre machine, ne joint que api.lever.co et api.eu.lever.co, garde ses réponses en mémoire le temps qu'il
tourne, et n'écrit rien sur le disque. PRIVACY.md dit ce qu'une
requête emporte et quels réglages changent cela.
Développement
npm install
npm run build:fixtures
npm test
npm run check
Les tests s'exécutent sur des fixtures engendrées et n'émettent aucune requête.
La suite en direct, npm run test:live, émet une requête par route et tourne
chaque nuit contre le service lui-même.
Contribuer
Les anomalies, les questions et les idées ont leur place dans le suivi d'incidents. Les propositions de modification sont bienvenues ; ouvrir un ticket d'abord aide à s'accorder sur la forme du changement. Voir CONTRIBUTING.md.
Licence
MIT, voir LICENSE. Les offres appartiennent aux entreprises qui les ont publiées.