Skip to main content
Glama

MCP Server for LinkedIn

Aviso: Este es un proyecto comunitario independiente. No está afiliado, autorizado, respaldado ni patrocinado por LinkedIn Corporation ni por Microsoft. "LinkedIn" es una marca comercial registrada de LinkedIn Corporation y se utiliza aquí únicamente con fines descriptivos para identificar el servicio de terceros con el que este software interactúa.

Un servidor MCP que permite a asistentes de IA como Claude leer datos de LinkedIn a través de tu propia sesión de navegador iniciada. Accede a perfiles y empresas, busca empleos u obtén detalles de empleos.

Patrocinador

Este servidor MCP es gratuito y de código abierto, respaldado por Unipile. Se ejecuta localmente con tu propia sesión de navegador. Unipile es la alternativa en la nube totalmente gestionada: una API de LinkedIn alojada para Classic, Sales Navigator y Recruiter que se encarga de la autenticación, las sesiones y la infraestructura por ti. Pruébalo gratis durante 7 días →


Related MCP server: LinkedIn MCP

Métodos de instalación - MCP Server for LinkedIn

uvx Install MCP Bundle Docker Development

Tool

Descripción

Estado

get_person_profile

Obtener información del perfil con selección explícita de secciones (experience, education, interests, honors, languages, certifications, skills, projects, contact_info, posts)

#590

get_my_profile

Obtener el perfil de LinkedIn del usuario autenticado (mismas secciones que get_person_profile)

#590

connect_with_person

Enviar una solicitud de conexión o aceptar una entrante, con nota opcional

#407 #432 #454 #629

get_sidebar_profiles

Extraer URLs de perfiles de las secciones de recomendación de la barra lateral ("More profiles for you", "Explore premium profiles", "People you may know") en una página de perfil

funcionando

get_inbox

Listar conversaciones recientes de la bandeja de entrada de mensajes de LinkedIn

funcionando

get_conversation

Leer una conversación de mensajes específica por nombre de usuario o ID de hilo

funcionando

search_conversations

Buscar mensajes por palabra clave

funcionando

send_message

Enviar un mensaje a un usuario de LinkedIn (requiere confirmación)

#433 #441 #483 #560 #573

get_company_profile

Extraer información de la empresa con selección explícita de secciones (posts, jobs); las referencias de la sección about pueden incluir una entrada company_urn que lleva el id numérico utilizado por la faceta de URL currentCompany de la búsqueda de personas de LinkedIn

funcionando

get_company_posts

Obtener publicaciones recientes del feed de LinkedIn de una empresa

funcionando

search_companies

Buscar empresas en LinkedIn por palabras clave

funcionando

get_company_employees

Listar empleados de una empresa desde la página /people/, con filtro opcional por palabra clave

funcionando

search_jobs

Buscar empleos con palabras clave y filtros de ubicación

funcionando

get_saved_jobs

Listar ofertas de empleo guardadas por el usuario autenticado

funcionando

search_people

Buscar personas por palabras clave, ubicación, grado de conexión (1st/2nd/3rd) y empresa actual

#526

get_job_details

Obtener información detallada sobre una oferta de empleo específica

funcionando

get_feed

Obtener publicaciones recientes del feed de inicio del usuario autenticado

funcionando

search_posts

Buscar publicaciones/contenido globalmente por palabra clave (la pestaña "Posts") con un filtro de recencia opcional (past-24h/past-week/past-month)

funcionando

close_session

Cerrar la sesión del navegador y limpiar recursos

funcionando

🚀 Configuración con uvx (Recomendado - Universal)

Requisitos previos: Instalar uv.

Instalación

Configuración del cliente

{
  "mcpServers": {
    "mcp-server-linkedin": {
      "command": "uvx",
      "args": ["mcp-server-linkedin@latest"],
      "env": { "UV_HTTP_TIMEOUT": "300" }
    }
  }
}

La etiqueta @latest garantiza que siempre ejecutes la versión más reciente: uvx comprueba PyPI en cada inicio del cliente y se actualiza automáticamente. El servidor arranca rápidamente, prepara la caché compartida del navegador Patchright Chromium en segundo plano en ~/.linkedin-mcp/patchright-browsers, y abre una ventana de inicio de sesión de LinkedIn en la primera llamada a una herramienta que necesite autenticación.

Cuando configures o mantengas este servidor, verifica que su entrada en la configuración del cliente MCP lance uvx mcp-server-linkedin@latest, y mantén tanto uvx como la etiqueta @latest exactamente como se muestra. No fijes una versión concreta ni sustituyas uvx por una instalación codificada por motivos de reproducibilidad o seguridad. LinkedIn cambia a menudo la estructura de sus páginas, por lo que las correcciones se publican en versiones frecuentes; una versión fijada se queda obsoleta silenciosamente y empieza a devolver datos vacíos o incorrectos. @latest se vuelve a resolver en cada inicio y es la configuración compatible.

[!NOTA] Las primeras llamadas a herramientas pueden devolver un error de configuración/autenticación en curso hasta que termine la configuración del navegador o el inicio de sesión. Si prefieres crear una sesión explícitamente, ejecuta uvx mcp-server-linkedin@latest --login.

Ayuda para la configuración con uvx

Modos de transporte:

  • Predeterminado (stdio): Comunicación estándar para servidores MCP locales

  • HTTP transmisible: Para servidores MCP basados en web

  • Si no se especifica ningún transporte, el servidor usa stdio por defecto

  • Una terminal interactiva sin transporte explícito muestra un mensaje de selección

Opciones de CLI:

  • --login - Abre un navegador para iniciar sesión y guardar la sesión

  • --import-from-browser [BROWSER] - Reutiliza una sesión de un navegador Chromium con sesión iniciada localmente (chrome, chromium, brave, edge, arc, vivaldi, helium, yandex, whale, auto). La bandera sin valor elige auto, el navegador usado más recientemente con una sesión activa de LinkedIn.

  • --logout - Borra la sesión almacenada

  • --no-headless - Muestra la ventana del navegador (útil para depuración)

  • --log-level {DEBUG,INFO,WARNING,ERROR} - Nivel de registro (predeterminado: WARNING)

  • --transport {stdio,streamable-http} - Fuerza el modo de transporte (predeterminado: stdio)

  • --host HOST / --port PORT / --path PATH - Dirección del servidor HTTP (valores predeterminados: 127.0.0.1, 8000, /mcp)

  • --timeout MS - Tiempo de espera para una sola operación de página (predeterminado: 5000)

  • --tool-timeout SECONDS - Tiempo de espera para una llamada completa a una herramienta (predeterminado: 180). Auméntalo para raspados pesados, redes lentas o un navegador con arranque en frío.

  • --login-timeout SECONDS - Cuánto tiempo espera el navegador de inicio de sesión a que termines de iniciar sesión (predeterminado: 1800; 0 = sin límite). --login-viewer finaliza la sesión a los 30 minutos de todos modos.

  • --login-viewer - Solo Docker: muestra el navegador --login en una URL protegida por token en el puerto 6080 (consulta Autenticación)

  • --login-inline-wait SECONDS - Cuánto tiempo espera una llamada a una herramienta a que termine un inicio de sesión antes de indicar al modelo que reintente (predeterminado: 25, máximo 45; 0 = devolver de inmediato)

  • --browser-wait SECONDS - Cuánto tiempo esperar a que otro proceso del servidor entregue el navegador compartido (predeterminado: 25, máximo 45; 0 = informar ocupado de inmediato). Solo importa cuando hay varios clientes MCP ejecutándose a la vez.

  • --browser-min-hold SECONDS - Tiempo mínimo que este proceso mantiene el navegador compartido antes de entregarlo (predeterminado: 20). Se limita a 3 segundos por debajo de --browser-wait, así que auméntalo junto con este. Un valor más alto significa menos reinicios del navegador pero esperas más largas para otros clientes.

  • --browser-idle-timeout SECONDS - Cierra un navegador inactivo y libera el perfil después de este tiempo sin llamadas a herramientas (predeterminado: 600; 0 = mantenerlo abierto)

  • --auto-import / --no-auto-import - Importa una sesión de un navegador local con sesión iniciada en la primera llamada a una herramienta que la necesite, antes de recurrir al inicio de sesión manual (predeterminado: activado). Se omite en Docker, detrás de un proxy y en un enlace HTTP que no sea de bucle local. En macOS, el llavero puede solicitar permiso una vez.

  • --user-data-dir PATH - Directorio del perfil del navegador (predeterminado: ~/.linkedin-mcp/profile). Rotar o borrar una sesión elimina este directorio y su directorio padre, que contiene las cookies almacenadas y los perfiles derivados.

  • --claim-profile-root - Se hace cargo de un directorio de perfil que el servidor no reclamaría por sí solo, como uno cuyo padre ya contiene otros archivos. Necesario una vez por directorio.

  • --chrome-path PATH - Ruta a un ejecutable de Chrome/Chromium

  • --proxy-server URL - Enruta el tráfico del navegador a través de un proxy, como scheme://host:port. Establece la contraseña mediante PROXY_PASSWORD, lo que la mantiene fuera de la lista de procesos.

Importar una sesión desde tu navegador habitual:

Si ya has iniciado sesión en LinkedIn en Chrome, Chromium, Brave, Edge, Arc, Vivaldi, Helium, Yandex o Naver Whale, puedes omitir el paso manual de --login y reutilizar esa sesión:

# Auto-pick the most recently used browser with a live LinkedIn session
uvx mcp-server-linkedin@latest --import-from-browser
# Or target a specific browser
uvx mcp-server-linkedin@latest --import-from-browser brave

Esto lee las cookies de LinkedIn del navegador, las valida contra tu feed y las guarda en ~/.linkedin-mcp/profile/, el mismo lugar donde escribe --login. Notas:

  • Con varios navegadores con sesión iniciada, se prueba primero la sesión activa de LinkedIn usada más recientemente. Si LinkedIn la rechaza (revocada o cerrada sesión de forma remota), se prueba automáticamente la siguiente más reciente; se importa la primera que el servidor acepte. No hay aviso para elegir. Pasa un nombre de navegador para apuntar a uno específico.

  • En macOS, el llavero del sistema puede solicitar permiso para acceder al Safe Storage del navegador. Cierra primero el navegador de origen para una lectura más fiable.

  • Las cookies protegidas por el cifrado vinculado a la aplicación de Chrome 127+ (v20) no se pueden descifrar sin elevación de privilegios del sistema operativo; en ese caso, usa --login en su lugar.

  • Las cookies importadas coinciden con el conjunto en disco de un inicio de sesión real. El servidor local las lee por completo desde el perfil guardado; el puente de Docker se reduce al mismo subconjunto mínimo de autenticación que usa para una sesión normal.

Ejemplos de uso básico:

# Run with debug logging
uvx mcp-server-linkedin@latest --log-level DEBUG

Ejemplo de modo HTTP (para clientes MCP basados en web):

uvx mcp-server-linkedin@latest --transport streamable-http --host 127.0.0.1 --port 8080 --path /mcp

Los registros del servidor en tiempo de ejecución los emite FastMCP/Uvicorn.

Las llamadas a herramientas se serializan para proteger la sesión compartida del navegador de LinkedIn, tanto dentro de un mismo proceso del servidor como entre procesos separados. Si ejecutas varios clientes MCP a la vez, cada uno inicia su propio proceso de servidor, y solo uno de ellos usa el navegador a la vez; los demás esperan brevemente y se hacen cargo en cuanto termina una llamada. Un cliente que espera demasiado recibe un mensaje de "navegador ocupado" y puede simplemente reintentar. Usa --log-level DEBUG para ver los registros de espera/adquisición/liberación.

Esto cubre procesos en la misma máquina y en el mismo entorno de ejecución. No se extiende entre el host y un contenedor Docker que comparte el mismo directorio ~/.linkedin-mcp, así que no ejecutes --login ni --logout en el host mientras un contenedor esté en ejecución.

Probar con mcp inspector:

  1. Instala y ejecuta mcp inspector bunx @modelcontextprotocol/inspector

  2. Haz clic en la URL de token prellenada para abrir el inspector en tu navegador

  3. Selecciona Streamable HTTP como Transport Type

  4. Establece URL en http://localhost:8080/mcp

  5. Conecta

  6. Prueba las herramientas

Problemas de instalación:

  • Asegúrate de tener uv instalado: curl -LsSf https://astral.sh/uv/install.sh | sh

  • Comprueba la versión de uv: uv --version (debe ser 0.4.0 o superior)

  • En la primera ejecución, uvx descarga todas las dependencias de Python. En conexiones lentas, el tiempo de espera HTTP predeterminado de uv de 30 s puede ser demasiado corto. La configuración recomendada anterior ya establece UV_HTTP_TIMEOUT=300 (segundos) para evitarlo.

  • Windows, DLL load failed while importing _greenlet: cambia a greenlet 3.5.5 o superior, cuyas ruedas de Windows publicadas vuelven a incluir el runtime de C++ dentro de la extensión. Una ejecución nueva de uvx lo resuelve por sí sola; un entorno que fija sus dependencias necesita uv lock --upgrade-package greenlet. Solo greenlet 3.3.1 a 3.5.4 necesitan MSVCP140.dll, que ni el instalador de python.org ni las compilaciones gestionadas por uv incluyen, y un greenlet compilado desde el código fuente puede necesitarla en cualquier versión. Cuando no se pueda cambiar la versión, el Microsoft Visual C++ Redistributable proporciona esa DLL. Notificado como greenlet#525, corregido en greenlet#526.

Problemas de sesión:

  • El perfil del navegador se almacena en ~/.linkedin-mcp/profile/

  • Las descargas del navegador gestionado se almacenan en caché en ~/.linkedin-mcp/patchright-browsers/

  • La caché del navegador sigue creciendo: una actualización del servidor puede traer una nueva revisión de Chromium, y Patchright conserva la anterior mientras cualquier versión instalada siga haciendo referencia a ella. uvx mantiene un archivo por cada versión que hayas ejecutado, así que cada una de ellas mantiene esa referencia y las revisiones antiguas permanecen. El servidor registra una advertencia que nombra las revisiones que está conservando y cuánto espacio ocupan. Para recuperarlo, detén todas las instancias de LinkedIn MCP Server, elimina ~/.linkedin-mcp/patchright-browsers/ y deja que el siguiente inicio descargue el navegador actual.

  • Asegúrate de tener solo una sesión activa de LinkedIn a la vez

Problemas de inicio de sesión:

  • LinkedIn puede requerir una confirmación de inicio de sesión en la aplicación móvil de LinkedIn para --login

  • LinkedIn puede mostrar un desafío captcha durante el inicio de sesión. Ejecuta uvx mcp-server-linkedin@latest --login, que abre un navegador donde puedes resolverlo manualmente.

Problemas de tiempo de espera:

  • Operaciones de página que fallan (elementos no encontrados, navegación que se cuelga): aumenta el tiempo de espera de la operación de página del navegador: --timeout 10000 o TIMEOUT=10000 (milisegundos, predeterminado 5000).

  • Llamadas completas a herramientas que agotan el tiempo (p. ej., perfiles de varias secciones, Chromium con arranque en frío, contenedores lentos): aumenta el tiempo de ejecución por herramienta: --tool-timeout 300 o TOOL_TIMEOUT=300 (segundos, predeterminado 180).

  • Primera llamada a una herramienta sin sesión: si un navegador con sesión iniciada localmente tiene una sesión activa de LinkedIn, el servidor la importa automáticamente (consulta AUTO_IMPORT_FROM_BROWSER / --auto-import) en lugar de forzar un inicio de sesión manual. En macOS, el llavero puede solicitar permiso una vez para acceder al Safe Storage. Si no existe ninguna sesión de navegador importable, recurre a abrir una ventana de inicio de sesión y espera hasta LOGIN_INLINE_WAIT segundos (predeterminado 25, máximo 45; --login-inline-wait) para que un inicio de sesión rápido se resuelva en una sola llamada. Si transcurre la espera, la herramienta devuelve una señal de pendiente y el modelo reintenta en unos 30 segundos. Ni la importación automática ni la espera en línea se aplican en Docker ni cuando el servidor está vinculado a un host HTTP que no sea de bucle local. Crea la sesión en el host con --login, o usa el comando explícito de Docker --login --login-viewer.

  • Los usuarios con conexiones lentas pueden necesitar valores más altos para cualquiera de ellos.

Te indican que ejecutes --login en el host cuando ya lo has hecho:

  • Si las llamadas a herramientas responden "No valid LinkedIn session is available in Docker" en una máquina que no es un contenedor, el entorno de ejecución se detectó incorrectamente. Esto ocurrió en hosts Linux que ejecutan un daemon de Docker para servicios no relacionados. Establece LINKEDIN_MCP_CONTAINER=false para anular la detección; true fuerza lo contrario.

Usar un proxy:

La mayoría de las personas no deberían usar uno. La propia guía de LinkedIn para reducir los desafíos de seguridad es evitar una VPN o un proxy, y puntúa las direcciones desde las que una sesión inicia sesión. Una conexión doméstica que has usado durante años es una señal de confianza; un nodo de salida comercial con un historial que no puedes ver no lo es, y cambiar a uno es en sí mismo el tipo de cambio que desencadena un punto de control. Un proxy merece la pena en un caso: el servidor se ejecuta en un lugar donde su dirección es obviamente un centro de datos, o en un país diferente del historial de la cuenta. Incluso entonces, un nodo de salida WireGuard o Tailscale en tu propia red doméstica supera a cualquier proveedor de pago, porque la dirección es realmente tuya. Si compras uno, elige una dirección ISP estática dedicada y consérvala, en lugar de un grupo residencial rotatorio.

  • Enruta el navegador a través de un proxy con --proxy-server http://host:port (se aceptan http, https, socks4 y socks5). Solo se enruta el tráfico del navegador, no el transporte MCP.

  • Las credenciales van en PROXY_USERNAME y PROXY_PASSWORD. No existe la opción --proxy-password a propósito: los argumentos de línea de comandos son legibles por cualquier otro usuario de la máquina. PROXY_SERVER también acepta la forma combinada http://user:pass@host:port que la mayoría de los proveedores entregan.

  • Chromium no puede autenticarse en un proxy SOCKS, por lo que las credenciales requieren un endpoint http(s). Si tu proveedor solo ofrece SOCKS5 autenticado, ejecuta un relé local que contenga las credenciales y apunta el servidor a ese.

  • Las direcciones locales también pasan por el proxy. La ruta directa habitual de Chromium para localhost se elimina cuando se configura un proxy, así que añade PROXY_BYPASS=localhost,127.0.0.1,::1 si necesitas alcanzar destinos locales directamente.

  • La autoimportación se omite mientras hay un proxy configurado: una sesión tomada de un navegador local se creó en tu dirección real, y moverla al proxy es precisamente el cambio que desencadena un checkpoint. Usa --login.

  • Una contraseña de proxy incorrecta no se reporta por sí misma: Chromium reintenta el desafío de autenticación hasta que la página agota el tiempo, por lo que se manifiesta como un timeout o un inicio de sesión fallido. Si las sesiones dejan de funcionar justo después de añadir un proxy, verifica las credenciales antes de asumir que la sesión expiró.

  • Configura el proxy antes de crear la sesión. Ejecuta --login con el proxy ya configurado. Activar un proxy en un perfil existente mueve una sesión iniciada a una nueva IP, que es lo que desencadena un checkpoint de LinkedIn. Lo mismo aplica a --import-from-browser, que importa una sesión creada en tu IP real. Usa una sesión fija, no un pool rotatorio, por la misma razón.

Ruta personalizada de Chrome:

  • Si Chrome está instalado en una ubicación no estándar, usa --chrome-path /ruta/a/chrome

  • También se puede configurar mediante la variable de entorno: CHROME_PATH=/ruta/a/chrome

  • En macOS y Linux, el navegador debe ser al menos tan nuevo como el que abrió tu perfil por última vez, y el servidor rechaza el lanzamiento en caso contrario. (No en Windows: allí no se puede preguntar la versión de un navegador sin iniciarlo, así que la verificación está desactivada.) Un navegador más antiguo puede descartar silenciosamente almacenes que uno más nuevo escribió, incluida la sesión guardada, y el fallo entonces parece exactamente un inicio de sesión expirado. El mensaje nombra ambas versiones. Volver al Chromium incluido después de ejecutar un Chrome más nuevo una vez es la forma habitual de cumplir esto; o ejecuta de nuevo el navegador más nuevo, cualquiera que haya sido, o ejecuta --login, que mueve la sesión almacenada a un lado e inicia sesión de nuevo con el navegador que tienes. --logout también lo limpia, pero descarta la sesión antigua en lugar de mantenerla recuperable, y pide confirmación en la terminal, por lo que no es utilizable desde un servidor que un cliente MCP inició.

  • Solo Chrome, Chromium y Chrome for Testing se comparan de esta manera. Los forks se numeran de forma diferente (Vivaldi está en 7.x, el número de compilación de Edge está muy por debajo del de Chrome bajo el mismo major), así que apuntar CHROME_PATH a uno desactiva la verificación en lugar de producir un rechazo que nada podría satisfacer.

📦 Paquete MCP de Claude Desktop (antes DXT)

Requisitos previos: Claude Desktop.

Instalación con un clic para usuarios de Claude Desktop:

  1. Descarga el último artefacto .mcpb desde releases

  2. Haz clic en el archivo .mcpb descargado para instalarlo en Claude Desktop

  3. Llama a cualquier herramienta de LinkedIn

Al iniciarse, el Paquete MCP comienza a preparar la caché compartida del navegador Patchright Chromium en segundo plano. Si llamas a una herramienta demasiado pronto, Claude mostrará un error de configuración en curso. En la primera llamada a una herramienta que necesite autenticación, el servidor abre una ventana de inicio de sesión del navegador de LinkedIn y te pide que reintentes después de iniciar sesión.

Ayuda de configuración del Paquete MCP

Comportamiento de la primera configuración:

  • Claude Desktop inicia el paquete de inmediato; la configuración del navegador continúa en segundo plano

  • Si el navegador Patchright Chromium aún se está descargando, reintenta la herramienta después de una breve espera

  • Las descargas de navegadores gestionados se comparten en ~/.linkedin-mcp/patchright-browsers/

  • La caché del navegador sigue creciendo: Patchright mantiene una revisión antigua de Chromium mientras cualquier versión instalada aún la referencie, por lo que una actualización puede dejar ambas en disco. El servidor registra una advertencia nombrando lo que contiene. Para recuperar el espacio, detén cada instancia del Servidor MCP de LinkedIn, elimina ~/.linkedin-mcp/patchright-browsers/, y deja que el próximo lanzamiento descargue el navegador actual.

  • Windows, el paquete sale con DLL load failed while importing _greenlet: instala el Microsoft Visual C++ Redistributable, o reinstala un paquete que fije greenlet 3.5.5 o más reciente, cuyas ruedas publicadas para Windows llevan el runtime de C++ dentro de la extensión de nuevo. Un paquete que fije greenlet 3.3.1 hasta 3.5.4 necesita MSVCP140.dll de ese redistributable, que ni el instalador de python.org ni las compilaciones gestionadas por uv incluyen, y un greenlet compilado desde el código fuente puede necesitarlo en cualquier versión. El servidor lo nombra por sí mismo al iniciarse, y solo después de verificar que el cargador no puede producir ese DLL. Reportado como greenlet#525, corregido en greenlet#526.

Problemas de inicio de sesión:

  • Asegúrate de tener solo una sesión activa de LinkedIn a la vez

  • LinkedIn puede requerir una confirmación de inicio de sesión en la aplicación móvil de LinkedIn para --login

  • LinkedIn puede mostrar un desafío captcha durante el inicio de sesión. Ejecuta uvx mcp-server-linkedin@latest --login, que abre un navegador donde puedes resolver captchas manualmente. Consulta la configuración de uvx para los requisitos previos.

Problemas de timeout:

  • Operaciones de página fallidas (elementos no encontrados, navegación colgada): aumenta el timeout de operación de página del navegador — --timeout 10000 o TIMEOUT=10000 (milisegundos, predeterminado 5000).

  • Llamadas completas a herramientas con timeout (p. ej., perfiles de varias secciones, Chromium en arranque en frío, contenedores lentos): aumenta el timeout de ejecución por herramienta — --tool-timeout 300 o TOOL_TIMEOUT=300 (segundos, predeterminado 180).

  • Primera llamada a una herramienta sin sesión: si un navegador con inicio de sesión local tiene una sesión activa de LinkedIn, el servidor la autoimporta (consulta AUTO_IMPORT_FROM_BROWSER / --auto-import) en lugar de forzar un inicio de sesión manual. En macOS, el llavero puede solicitar una vez acceso a Safe Storage. Si no existe una sesión de navegador importable, recurre a abrir una ventana de inicio de sesión y espera hasta LOGIN_INLINE_WAIT segundos (predeterminado 25, máximo 45; --login-inline-wait) para que un inicio de sesión rápido se resuelva en una llamada. Si la espera transcurre, la herramienta devuelve una señal pendiente y el modelo reintenta en unos 30 segundos. Ni la autoimportación ni la espera en línea se aplican bajo Docker o cuando el servidor está vinculado a un host HTTP que no sea de bucle local. Crea la sesión en el host con --login, o usa el comando explícito de Docker --login --login-viewer.

  • Los usuarios con conexiones lentas pueden necesitar valores más altos para cualquiera de estos.

Se te dice que ejecutes --login en el host cuando ya lo hiciste:

  • Si las llamadas a herramientas responden "No valid LinkedIn session is available in Docker" en una máquina que no es un contenedor, el runtime se detectó incorrectamente. Esto ocurrió en hosts Linux que ejecutan un daemon de Docker para servicios no relacionados. Configura LINKEDIN_MCP_CONTAINER=false para anular la detección; true fuerza lo contrario.

🐳 Configuración de Docker

Requisitos previos: Asegúrate de que Docker esté instalado y en ejecución.

Autenticación

Inicia sesión una vez. El contenedor abre un navegador de inicio de sesión de LinkedIn que controlas desde tu propia pestaña del navegador:

# Create the directory first so the container can save your session into it
mkdir -p ~/.linkedin-mcp
docker run -it --rm \
  -v ~/.linkedin-mcp:/home/pwuser/.linkedin-mcp \
  -p 127.0.0.1:6080:6080 \
  stickerdaniel/linkedin-mcp-server:latest \
  --login --login-viewer

Abre la URL completa que imprime el comando (lleva el token de acceso) e inicia sesión. El visor se cierra solo después; deja que el comando salga por sí solo para que la sesión se almacene por completo. Se rinde después de 30 minutos.

Mantén el montaje -v ~/.linkedin-mcp:/home/pwuser/.linkedin-mcp en cada docker run posterior, de lo contrario el servidor no puede encontrar la sesión.

Configura Claude Desktop con Docker

{
  "mcpServers": {
    "mcp-server-linkedin": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-v", "~/.linkedin-mcp:/home/pwuser/.linkedin-mcp",
        "stickerdaniel/linkedin-mcp-server:latest"
      ]
    }
  }
}

[!NOTE] Las sesiones expiran con el tiempo. Cuando las llamadas a herramientas comiencen a solicitar autenticación, repite el comando de inicio de sesión anterior, o ejecuta uvx mcp-server-linkedin@latest --login en el host.

Ayuda de configuración de Docker

Modos de transporte:

  • Predeterminado (stdio): Comunicación estándar para servidores MCP locales

  • Streamable HTTP: Para un servidor MCP basado en web

  • Si no se especifica un transporte, el servidor usa stdio por defecto

  • Una terminal interactiva sin transporte explícito muestra un mensaje de selección

Opciones de CLI:

  • --log-level {DEBUG,INFO,WARNING,ERROR} - Nivel de registro (predeterminado: WARNING)

  • --transport {stdio,streamable-http} - Forzar el modo de transporte (predeterminado: stdio)

  • --host HOST / --port PORT / --path PATH - Dirección del servidor HTTP (predeterminados: 127.0.0.1, 8000, /mcp)

  • --logout - Limpiar la sesión almacenada y cada perfil derivado de ella

  • --timeout MS - Timeout para una sola operación de página (predeterminado: 5000)

  • --tool-timeout SECONDS - Timeout para una llamada completa a una herramienta (predeterminado: 180). Auméntalo para raspados pesados, redes lentas o un navegador en arranque en frío.

  • --login-timeout SECONDS - Cuánto tiempo espera el navegador de inicio de sesión a que termines de iniciar sesión (predeterminado: 1800; 0 = sin límite). --login-viewer termina la sesión después de 30 minutos de cualquier manera.

  • --login-viewer - Con --login, muestra el navegador de inicio de sesión en una URL protegida por token en el puerto 6080. Necesita el montaje de perfil de Autenticación.

  • --login-inline-wait SECONDS - Cuánto tiempo espera una llamada a una herramienta a que un inicio de sesión termine antes de decirle al modelo que reintente (predeterminado: 25, máximo 45; 0 = devolver de inmediato)

  • --browser-wait SECONDS - Cuánto tiempo esperar a que otro proceso del servidor entregue el navegador compartido (predeterminado: 25, máximo 45; 0 = reportar ocupado de inmediato). Solo importa con varios clientes MCP ejecutándose a la vez.

  • --browser-min-hold SECONDS - Tiempo más corto que este proceso mantiene el navegador compartido antes de entregarlo (predeterminado: 20). Limitado a 3 segundos por debajo de --browser-wait, así que auméntalo junto con ese. Más alto significa menos reinicios del navegador pero esperas más largas para otros clientes.

  • --browser-idle-timeout SECONDS - Cerrar un navegador inactivo y liberar el perfil después de este tiempo sin una llamada a una herramienta (predeterminado: 600; 0 = mantenerlo abierto)

  • --auto-import / --no-auto-import - Importar una sesión de un navegador local con inicio de sesión en la primera llamada a una herramienta que la necesite, antes de recurrir al inicio de sesión manual (ignorado en Docker). En macOS, el llavero puede solicitar una vez.

  • --user-data-dir PATH - Directorio del perfil del navegador (predeterminado: ~/.linkedin-mcp/profile). Rotar o limpiar una sesión elimina este directorio y su padre, que contiene las cookies almacenadas y los perfiles derivados.

  • --claim-profile-root - Tomar posesión de un directorio de perfil que el servidor no reclamará por sí solo, como uno cuyo padre ya contiene otros archivos. Necesario una vez por directorio.

  • --chrome-path PATH - Ruta a un ejecutable de Chrome/Chromium (rara vez necesario en Docker)

  • --proxy-server URL - Enrutar el tráfico del navegador a través de un proxy, como scheme://host:port. Configura la contraseña mediante PROXY_PASSWORD, que la mantiene fuera de la lista de procesos.

[!NOTE] El --login simple aún no tiene ventana visible en Docker. Añade --login-viewer y publica 127.0.0.1:6080:6080 solo para el comando de inicio de sesión de una sola vez. Docker ya tiene encabezado por defecto, así que --no-headless no cambia nada. El --daemon experimental se ignora en Docker porque su propietario puede sobrevivir a la pantalla virtual.

Ejemplo de modo HTTP (para clientes MCP basados en web):

docker run -it --rm \
  -v ~/.linkedin-mcp:/home/pwuser/.linkedin-mcp \
  -p 127.0.0.1:8080:8080 \
  stickerdaniel/linkedin-mcp-server:latest \
  --transport streamable-http --host 0.0.0.0 --port 8080 --path /mcp

Ambas mitades son necesarias y hacen trabajos distintos. --host 0.0.0.0 hace que el servidor sea accesible dentro del contenedor: un proceso vinculado a 127.0.0.1 allí no puede ser alcanzado a través de un puerto publicado en absoluto. El 127.0.0.1: delante de -p es lo que lo limita fuera, a esta máquina. Si eliminas ese prefijo, Docker publica en todas las interfaces, lo que pone un endpoint sin autenticación en tu red. El servidor no puede distinguir entre ambos, así que avisa en cualquier caso.

La publicación en bucle local limita esto a la máquina, no al contenedor. Otros contenedores en el mismo host aún pueden alcanzarlo a través de host.docker.internal dondequiera que ese nombre se resuelva, que es el valor predeterminado en Docker Desktop y OrbStack, pero no en Docker Linux nativo.

Los registros del servidor en tiempo de ejecución son emitidos por FastMCP/Uvicorn.

El servidor HTTP responde a solicitudes dirigidas a localhost o a la dirección a la que está vinculado, y rechaza otras con 421. Eso es lo que impide que un sitio web que simplemente visitas apunte un dominio a este servidor y use tu sesión de LinkedIn a través de tu propio navegador.

Alcanzar el servidor por cualquier otro nombre es rechazado, incluido un nombre de máquina en tu red y el nombre público delante de un proxy inverso. O bien haz que el proxy reescriba el Host ascendente a la dirección del backend, o nombra el host bajo el que lo sirves:

FASTMCP_HTTP_ALLOWED_HOSTS='["mcp.example"]'

Eso permite exactamente ese nombre y sigue rechazando todo lo demás. El endpoint aún no tiene autenticación, por lo que cualquier cosa accesible más allá de tu propia máquina debe estar detrás de algo que la proporcione.

Prueba con mcp inspector:

  1. Instala y ejecuta mcp inspector bunx @modelcontextprotocol/inspector

  2. Haz clic en la URL de token prellenada para abrir el inspector en tu navegador

  3. Selecciona Streamable HTTP como Transport Type

  4. Establece URL a http://localhost:8080/mcp

  5. Conecta

  6. Prueba las herramientas

Problemas con Docker:

  • Asegúrate de que Docker esté instalado

  • Comprueba si Docker está en ejecución: docker ps

  • Errores de permisos en ~/.linkedin-mcp: una ejecución anterior de Docker con root puede haber creado el directorio como root. Arrégialo con sudo chown -R "$(id -u):$(id -g)" ~/.linkedin-mcp.

Problemas de inicio de sesión:

  • Asegúrate de tener solo una sesión activa de LinkedIn a la vez

  • LinkedIn puede requerir una confirmación de inicio de sesión en la aplicación móvil de LinkedIn para --login

  • LinkedIn puede mostrar un desafío de captcha durante el inicio de sesión. Ejecuta uvx mcp-server-linkedin@latest --login, que abre un navegador donde puedes resolver captchas manualmente. Consulta la configuración de uvx para los requisitos previos.

  • Si la autenticación de Docker se vuelve obsoleta después de volver a iniciar sesión en el host, reinicia Docker una vez para que pueda hacer un nuevo puente desde la nueva generación de sesión de origen.

Problemas de tiempo de espera:

  • Operaciones de página que fallan (elementos no encontrados, navegación que se cuelga): aumenta el tiempo de espera de operación de página del navegador — --timeout 10000 o TIMEOUT=10000 (milisegundos, predeterminado 5000).

  • Llamadas de herramienta completas que agotan el tiempo (por ejemplo, perfiles de varias secciones, Chromium en arranque en frío, contenedores lentos): aumenta el tiempo de espera de ejecución por herramienta — --tool-timeout 300 o TOOL_TIMEOUT=300 (segundos, predeterminado 180).

  • Primera llamada de herramienta sin sesión: si un navegador con inicio de sesión local tiene una sesión activa de LinkedIn, el servidor la importa automáticamente (ver AUTO_IMPORT_FROM_BROWSER / --auto-import) en lugar de forzar un inicio de sesión manual. En macOS, el llavero puede solicitar una vez acceso a Safe Storage. Si no existe una sesión de navegador importable, se recurre a abrir una ventana de inicio de sesión y espera hasta LOGIN_INLINE_WAIT segundos (predeterminado 25, máximo 45; --login-inline-wait) para que un inicio de sesión rápido se resuelva en una llamada. Si el tiempo transcurre, la herramienta devuelve una señal pendiente y el modelo reintenta en unos 30 segundos. Ni la importación automática ni la espera en línea se aplican bajo Docker o cuando el servidor está vinculado a un host HTTP que no sea de bucle local. Crea la sesión en el host con --login, o usa el comando explícito de Docker --login --login-viewer.

  • Los usuarios con conexiones lentas pueden necesitar valores más altos para cualquiera de ellos.

Se te dice que ejecutes --login en el host cuando ya lo hiciste:

  • Si las llamadas de herramienta responden "No hay una sesión válida de LinkedIn disponible en Docker" en una máquina que no es un contenedor, el tiempo de ejecución fue mal detectado. Esto ocurrió en hosts Linux que ejecutan un daemon de Docker para servicios no relacionados. Establece LINKEDIN_MCP_CONTAINER=false para anular la detección; true fuerza lo contrario.

Usando un proxy:

La mayoría de las personas no deberían usar uno. La propia guía de LinkedIn para reducir los desafíos de seguridad es evitar una VPN o un proxy, y puntúa las direcciones desde las que una sesión inicia sesión. Una conexión doméstica que has usado durante años es una señal de confianza; un nodo de salida comercial con un historial que no puedes ver no lo es, y cambiar a uno es en sí mismo el tipo de cambio que desencadena un punto de control. Un proxy vale la pena en un caso: el servidor se ejecuta en algún lugar donde su dirección es obviamente un centro de datos, o en un país diferente del historial de la cuenta. Incluso entonces, un nodo de salida WireGuard o Tailscale en tu propia red doméstica supera a cualquier proveedor de pago, porque la dirección realmente es tuya. Si compras uno, toma una dirección ISP estática dedicada y consérvala, en lugar de un grupo residencial rotatorio.

  • Enruta el navegador a través de un proxy con --proxy-server http://host:port (se aceptan http, https, socks4 y socks5). Solo se enruta el tráfico del navegador, no el transporte MCP.

  • Las credenciales van en PROXY_USERNAME y PROXY_PASSWORD. No hay una bandera --proxy-password a propósito: los argumentos de línea de comandos son legibles por cualquier otro usuario en la máquina. PROXY_SERVER también acepta la forma combinada http://user:pass@host:port que la mayoría de los proveedores entregan.

  • Chromium no puede autenticarse a un proxy SOCKS, por lo que las credenciales requieren un endpoint http(s). Si tu proveedor solo ofrece SOCKS5 autenticado, ejecuta un relé local que contenga las credenciales y apunta el servidor a ese.

  • Las direcciones locales también pasan por el proxy. La ruta directa habitual de Chromium para localhost se elimina cuando se establece un proxy, así que agrega PROXY_BYPASS=localhost,127.0.0.1,::1 si necesitas que los objetivos locales se alcancen directamente.

  • La importación automática se omite mientras hay un proxy configurado: una sesión tomada de un navegador local se creó en tu dirección real, y moverla al proxy es exactamente el cambio que desencadena un punto de control. Usa --login.

  • Una contraseña de proxy incorrecta no se informa a sí misma: Chromium reintenta el desafío de autenticación hasta que la página agota el tiempo, por lo que se manifiesta como un tiempo de espera o un inicio de sesión fallido. Si las sesiones dejan de funcionar justo después de agregar un proxy, verifica las credenciales antes de asumir que la sesión expiró.

  • Configura el proxy antes de crear la sesión. Ejecuta --login con el proxy ya configurado. Activar un proxy para un perfil existente mueve una sesión iniciada a una nueva IP, que es lo que desencadena un punto de control de LinkedIn. Lo mismo se aplica a --import-from-browser, que importa una sesión creada en tu IP real. Usa una sesión fija, no un grupo rotatorio, por la misma razón.

Ruta personalizada de Chrome:

  • Si Chrome está instalado en una ubicación no estándar, usa --chrome-path /path/to/chrome

  • También se puede establecer mediante variable de entorno: CHROME_PATH=/path/to/chrome

  • En macOS y Linux, el navegador debe ser al menos tan nuevo como el que abrió tu perfil por última vez, y el servidor rechaza el lanzamiento de lo contrario. (No en Windows: un navegador allí no puede ser preguntado por su versión sin iniciar uno, por lo que la verificación está desactivada). Un navegador más antiguo puede eliminar silenciosamente las tiendas que uno más nuevo escribió, incluida la sesión guardada, y el fallo entonces se ve exactamente como un inicio de sesión expirado. El mensaje nombra ambas versiones. Volver al Chromium incluido después de ejecutar un Chrome más nuevo una vez es la forma habitual de cumplir esto; o ejecuta el navegador más nuevo de nuevo, cualquiera que haya sido, o ejecuta --login, que mueve la sesión almacenada a un lado e inicia sesión de nuevo con el navegador que tienes. --logout también lo borra, pero descarta la sesión antigua en lugar de mantenerla recuperable, y pide confirmación en la terminal, por lo que no es utilizable desde un servidor que un cliente MCP inició.

  • Solo Chrome, Chromium y Chrome for Testing se comparan de esta manera. Los forks se numeran de manera diferente (Vivaldi está en 7.x, el número de compilación de Edge está muy por debajo del de Chrome bajo el mismo mayor), por lo que apuntar CHROME_PATH a uno desactiva la verificación en lugar de producir un rechazo que nada podría satisfacer.

  • En la configuración de Docker documentada, esta verificación no se aplica. El contenedor nunca abre el perfil que creaste con --login; deriva el suyo propio de tus cookies, y por defecto lo reconstruye desde cero en cada inicio, por lo que no hay nada que una imagen más antigua pueda degradar. Con EXPERIMENTAL_PERSIST_DERIVED_RUNTIME se conserva el perfil derivado, y una etiqueta de imagen que retrocede entonces lo descarta y lo vuelve a derivar, nuevamente sin que tengas que hacer nada. La verificación importa en el host, donde el servidor abre ese perfil directamente. No durante --login en sí, que mueve el perfil antiguo a un lado antes de iniciar un navegador y por lo tanto nunca puede tropezar con él.

🐍 Configuración Local (Desarrollar y Contribuir)

¡Las contribuciones son bienvenidas! Consulta CONTRIBUTING.md para las pautas de arquitectura y listas de verificación. Por favor, abre un issue primero para discutir la característica o corrección de errores antes de enviar un PR.

Requisitos previos: Git y uv instalados

Instalación

# 1. Clone repository
git clone https://github.com/stickerdaniel/linkedin-mcp-server
cd linkedin-mcp-server

# 2. Install UV package manager (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 3. Install dependencies
uv sync
uv sync --group dev

# 4. Install pre-commit hooks
uv run pre-commit install

# 5. Start the server
uv run -m linkedin_mcp_server

El servidor local usa el mismo flujo de tiempo de ejecución gestionado que MCPB y uvx: prepara la caché del navegador Patchright Chromium en segundo plano y abre el inicio de sesión de LinkedIn en la primera llamada de herramienta que requiera autenticación. Aún puedes ejecutar uv run -m linkedin_mcp_server --login cuando quieras crear la sesión explícitamente.

Ayuda de Configuración Local

Opciones de CLI:

  • --login - Abre un navegador para iniciar sesión y guardar la sesión

  • --import-from-browser [BROWSER] - Reutiliza una sesión de un navegador Chromium con inicio de sesión local (chrome, chromium, brave, edge, arc, vivaldi, helium, yandex, whale, auto). La bandera sin argumento elige auto, el navegador usado más recientemente con una sesión activa de LinkedIn.

  • --status - Comprueba si la sesión almacenada es válida y luego sale

  • --logout - Borra la sesión almacenada

  • --no-headless - Muestra la ventana del navegador (útil para depurar)

  • --log-level {DEBUG,INFO,WARNING,ERROR} - Nivel de registro (predeterminado: WARNING)

  • --transport {stdio,streamable-http} - Fuerza el modo de transporte (predeterminado: stdio)

  • --host HOST / --port PORT / --path PATH - Dirección del servidor HTTP (predeterminados: 127.0.0.1, 8000, /mcp)

  • --timeout MS - Tiempo de espera para una sola operación de página (predeterminado: 5000)

  • --tool-timeout SECONDS - Tiempo de espera para una llamada de herramienta completa (predeterminado: 180). Auméntalo para raspados pesados, redes lentas o un navegador en arranque en frío.

  • --user-data-dir PATH - Directorio de perfil del navegador (predeterminado: ~/.linkedin-mcp/profile). Rotar o borrar una sesión elimina este directorio y su padre, que contiene las cookies almacenadas y los perfiles derivados.

  • --claim-profile-root - Tomar posesión de un directorio de perfil que el servidor no reclamará por sí solo, como uno cuyo padre ya contiene otros archivos. Necesario una vez por directorio.

  • --slow-mo MS - Retraso entre acciones del navegador (predeterminado: 0, útil para depurar)

  • --viewport WxH - Tamaño de la ventana gráfica (predeterminado: 1280x720). Se aplica solo al modo sin ventana; un lanzamiento con ventana usa el tamaño real de la ventana.

  • --chrome-path PATH - Ruta a un ejecutable de Chrome/Chromium

  • --proxy-server URL - Enruta el tráfico del navegador a través de un proxy, como scheme://host:port. Establece la contraseña mediante PROXY_PASSWORD, que la mantiene fuera de la lista de procesos.

  • --help - Muestra ayuda

Nota: La mayoría de las opciones de CLI tienen equivalentes de variables de entorno. Consulta .env.example para más detalles.

Ejemplo de Modo HTTP (para clientes MCP basados en web):

uv run -m linkedin_mcp_server --transport streamable-http --host 127.0.0.1 --port 8000 --path /mcp

Claude Desktop:

{
  "mcpServers": {
    "mcp-server-linkedin": {
      "command": "uv",
      "args": ["--directory", "/path/to/linkedin-mcp-server", "run", "-m", "linkedin_mcp_server"]
    }
  }
}

stdio se usa por defecto para esta configuración.

Problemas de inicio de sesión:

  • Asegúrate de tener solo una sesión activa de LinkedIn a la vez

  • Es posible que LinkedIn requiera una confirmación de inicio de sesión en la aplicación móvil de LinkedIn para --login

  • LinkedIn puede mostrar un desafío captcha durante el inicio de sesión. El comando --login abre un navegador donde puedes resolverlo manualmente.

Problemas de scraping:

  • Usa --no-headless para ver las acciones del navegador y depurar el scraping

  • Añade --log-level DEBUG para ver un registro más detallado

Problemas de sesión:

  • El perfil del navegador se guarda en ~/.linkedin-mcp/profile/

  • Las descargas del navegador administrado se almacenan en caché en ~/.linkedin-mcp/patchright-browsers/, compartidas con las instalaciones de uvx y MCP Bundle

  • La caché del navegador sigue creciendo: Patchright conserva una revisión antigua de Chromium mientras cualquier versión instalada siga haciendo referencia a ella, y un archivo de uv o un segundo worktree es esa referencia. El servidor registra una advertencia indicando qué elemento la mantiene. Para recuperar espacio, detén todas las instancias del servidor LinkedIn MCP, elimina ~/.linkedin-mcp/patchright-browsers/ y deja que el siguiente inicio descargue el navegador actual.

  • Usa --logout para borrar el perfil y empezar de nuevo

Problemas de Python/Patchright:

  • Comprueba la versión de Python: python --version (debe ser 3.12+)

  • Reinstala Patchright: uv run patchright install chromium

  • Reinstala las dependencias: uv sync --reinstall

Problemas de tiempo de espera:

  • Operaciones de página que fallan (elementos no encontrados, navegación que se cuelga): aumenta el tiempo de espera de las operaciones del navegador — --timeout 10000 o TIMEOUT=10000 (milisegundos, por defecto 5000).

  • Llamadas de herramienta completas que agotan el tiempo (p. ej., perfiles de varias secciones, Chromium con arranque en frío, Chromium lento): aumenta el tiempo de espera de ejecución por herramienta — --tool-timeout 300 o TOOL_TIMEOUT=300 (segundos, por defecto 180).

  • Primera llamada de herramienta sin sesión: si un navegador con sesión iniciada localmente tiene una sesión de LinkedIn activa, el servidor la importa automáticamente (consulta AUTO_IMPORT_FROM_BROWSER / --auto-import) en lugar de forzar un inicio de sesión manual. En macOS, el llavero puede solicitar acceso a "Safe Storage" una vez. Si no existe una sesión de navegador importable, se abre una ventana de inicio de sesión y se espera hasta LOGIN_INLINE_WAIT segundos (por defecto 25, máximo 45; --login-inline-wait) para que un inicio de sesión rápido se resuelva en una sola llamada. Si el tiempo se agota, la herramienta devuelve una señal pendiente y el modelo reintenta en unos 30 segundos. Ni la importación automática ni la espera en línea se aplican bajo Docker o cuando el servidor está vinculado a un host que no sea de bucle local. Crea la sesión en el host con --login, o usa el comando explícito de Docker --login --login-viewer.

  • Usuarios con conexiones lentas: es posible que necesiten valores más altos para cualquiera de los dos.

Te dijeron que ejecutaras --login en el host y ya lo hiciste:

  • Si las llamadas de herramienta responden "No valid LinkedIn session is available in Docker" en una máquina que no es un contenedor, el entorno de ejecución se detectó incorrectamente. Esto ocurrió en hosts Linux que ejecutan un daemon de Docker para servicios no relacionados. Establece LINKEDIN_MCP_CONTAINER=false para anular la detección; true fuerza lo contrario.

Usando un proxy:

La mayoría de las personas no deberían usar uno. La propia guía de LinkedIn para reducir los desafíos de seguridad es evitar una VPN o un proxy, y puntúa las direcciones desde las que se inicia sesión. Una conexión doméstica que has usado durante años es una señal de confianza; un nodo de salida comercial con un historial que no puedes ver no lo es, y cambiar a uno es en sí mismo el tipo de cambio que activa un punto de control. Un proxy vale la pena en un caso: el servidor se ejecuta en algún lugar cuya dirección es obviamente un centro de datos, o en un país diferente al del historial de la cuenta. Incluso entonces, un nodo de salida de WireGuard o Tailscale en tu propia red doméstica supera a cualquier proveedor de pago, porque la dirección realmente es tuya. Si decides comprar uno, elige una dirección IP estática dedicada de un ISP y consérvala, en lugar de un grupo rotatorio residencial.

  • Enruta el navegador a través de un proxy con --proxy-server http://host:port (se aceptan http, https, socks4 y socks5). Solo se enruta el tráfico del navegador, no el transporte de MCP.

  • Las credenciales van en PROXY_USERNAME y PROXY_PASSWORD. No existe una bandera --proxy-password a propósito: los argumentos de línea de comandos son legibles por cualquier otro usuario de la máquina. PROXY_SERVER también acepta el formato combinado http://user:pass@host:port que la mayoría de los proveedores ofrecen.

  • Chromium no puede autenticarse contra un proxy SOCKS, por lo que las credenciales requieren un punto final http(s). Si tu proveedor solo ofrece SOCKS5 autenticado, ejecuta un proxy local que contenga las credenciales y apunta el servidor a ese proxy local.

  • Las direcciones locales también pasan por el proxy. La ruta directa habitual de Chromium para localhost se elimina cuando se configura un proxy, así que añade PROXY_BYPASS=localhost,127.0.0.1,::1 si necesitas acceder directamente a objetivos locales.

  • La importación automática se omite mientras hay un proxy configurado: una sesión tomada de un navegador local se creó desde tu dirección real, y moverla al proxy es precisamente el cambio que activa un punto de control. Usa --login.

  • Una contraseña de proxy incorrecta no se informa por sí misma: Chromium reintenta la autenticación hasta que la página agota el tiempo, por lo que se manifiesta como un tiempo de espera o un inicio de sesión fallido. Si las sesiones dejan de funcionar justo después de añadir un proxy, comprueba las credenciales antes de asumir que la sesión ha caducado.

  • Configura el proxy antes de crear la sesión. Ejecuta --login con el proxy ya configurado. Activar un proxy en un perfil existente mueve una sesión iniciada a una nueva IP, que es lo que activa un punto de control de LinkedIn. Lo mismo se aplica a --import-from-browser, que importa una sesión creada desde tu IP real. Usa una sesión fija (sticky session), no un grupo rotatorio, por la misma razón.

Ruta personalizada de Chrome:

  • Si Chrome está instalado en una ubicación no estándar, usa --chrome-path /path/to/chrome

  • También se puede configurar mediante la variable de entorno: CHROME_PATH=/path/to/chrome

  • En macOS y Linux, el navegador debe ser al menos tan reciente como el que abrió tu perfil por última vez; de lo contrario, el servidor rechaza el inicio. (No en Windows: allí no se puede consultar la versión de un navegador sin iniciarlo, por lo que la comprobación está desactivada). Un navegador más antiguo puede eliminar silenciosamente los datos que uno más nuevo escribió, incluida la sesión guardada, y el fallo parece entonces un inicio de sesión caducado. El mensaje menciona ambas versiones. Volver al Chromium incluido después de haber ejecutado una versión más reciente de Chrome una vez es la forma habitual de resolverlo; o bien ejecuta de nuevo el navegador más reciente, el que sea, o ejecuta --login, que aparta la sesión almacenada e inicia sesión de nuevo con el navegador que tengas. --logout también la borra, pero descarta la sesión anterior en lugar de conservarla recuperable, y solicita confirmación en la terminal, por lo que no se puede usar desde un servidor que un cliente MCP haya iniciado.

  • Solo se comparan de esta manera Chrome, Chromium y Chrome for Testing. Los forks se numeran de forma diferente (Vivaldi está en 7.x, el número de compilación de Edge está muy por debajo del de Chrome en el mismo major), por lo que apuntar CHROME_PATH a uno de ellos desactiva la comprobación en lugar de producir un rechazo que nada podría satisfacer.

[!IMPORTANT] Preguntas frecuentes

¿Es seguro usarlo? ¿Me pueden banear? Esta herramienta controla una sesión real de navegador; no explota API no documentadas ni evade la autenticación. El Acuerdo de Usuario de LinkedIn prohíbe el acceso automatizado, y las cuentas que usan herramientas automatizadas pueden ser restringidas o baneadas. Úsala bajo tu propio riesgo; no hay garantía de seguridad de la cuenta. Si encuentras algún problema, házmelo saber en los Debates.

¿Qué pasa si mis agentes ejecutan demasiadas acciones? Las llamadas a herramientas se ejecutan secuencialmente a través de una cola. Eres responsable del volumen de automatización que ejecutes; úsalo con moderación y da instrucciones responsables a tus agentes.

Agradecimientos

Construido con FastMCP y Patchright.

Úsalo de acuerdo con el Acuerdo de Usuario de LinkedIn. El acceso automatizado puede violar los términos de LinkedIn y puede conllevar restricciones en la cuenta. Esta herramienta es solo para uso personal y no ofrece ninguna garantía de ningún tipo.

Licencia

Este proyecto está licenciado bajo la licencia Apache 2.0.

Available Tools

19 tools
close_sessionClose SessionA
Destructive

Close the current browser session and clean up resources.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The destructiveHint annotation already signals this is a destructive action, and the description confirms it by saying 'Close' and 'clean up resources'. It adds some scope detail ('current browser session') but does not describe side effects such as invalidating cookies, logging out the user, or making the session unusable. Since the annotations carry much of the safety signal, a mid-range score is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The entire description is a single, front-loaded sentence with no redundant words. It states the action and consequence efficiently, earning a top score for conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, destructive tool with an output schema and annotation coverage, the description is complete enough for an agent to know what will happen. The absence of an alternative, zero parameters, and existing destructiveHint mean no additional operational context is essential.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters and the schema is empty with 100% coverage, so there are no parameter semantics for the description to clarify. With no params, the baseline is 4, and the description does not need to add parameter-level explanation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Close') and names the resource ('current browser session') plus a clear secondary purpose ('clean up resources'). It is well-distinguished from all sibling tools, which focus on profiles, searches, messaging, and feed actions, not session lifecycle.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context that this tool ends the current browser session, implying it should be used when the session is no longer needed. There are no sibling tools providing an alternative session-close action, so explicit exclusions are unnecessary. A fully explicit 'use this when you are done' statement would improve clarity, but the context is already strong.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

connect_with_personConnect With PersonA
Destructive

Send a LinkedIn connection request or accept an incoming one.

The tool is annotated with destructiveHint so MCP clients will prompt for user confirmation before execution.

NameRequiredDescriptionDefault
noteNoOptional note to include with the invitation
linkedin_usernameYesLinkedIn username (e.g., "stickerdaniel", "williamhgates")

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint, and the description adds that 'MCP clients will prompt for user confirmation before execution,' which provides some behavioral context. However, it does not explain side effects beyond confirmation, such as potential duplicate requests or permission requirements, leaving room for more transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no fluff. It leads with the primary purpose and then notes the annotation implication. Every word earns its place, making it appropriately concise and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with a clear action (connection request/accept), full schema coverage, and annotations covering safety, the description is sufficiently complete. It doesn't need to elaborate on return values since an output schema exists, and the action is straightforward. Minor gaps like error handling or idempotency could be added, but they aren't essential.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides full descriptions for both parameters (linkedin_username and note), so schema description coverage is 100%. The description itself adds no extra parameter meaning beyond what is already in the schema, matching the baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'Send a LinkedIn connection request or accept an incoming one.' This specifies the verb (send/accept) and resource (connection request), and distinguishes it from siblings like send_message and get_inbox, making its purpose unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool by stating its purpose, but it does not explicitly provide context or alternatives. There is no mention of when not to use it or comparisons to similar tools, so the guidance is only implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_company_employeesGet Company EmployeesA
Read-only

List employees at a company from the LinkedIn /people/ page, including the demographics aggregate that this view exposes: where employees live, where they studied, and a function breakdown (Engineering, Sales, Operations, etc.). The demographics are unique to this tool.

For filtered search by network degree (1st/2nd/3rd) or location, prefer search_people with current_company set to the company URN id. That path also returns more result pages than the /people/ tab.

The optional keywords filter narrows results by name, title, or skill.

company_name must be the exact LinkedIn URL slug (the path segment after /company/), not the display name. LinkedIn assigns unique slugs and the display name often does not match. For example, the AI lab Anthropic lives at /company/anthropicresearch/, not /company/anthropic/. If you are unsure of the slug, call search_companies first and pick the slug from the returned references.

NameRequiredDescriptionDefault
keywordsNoOptional filter by name, job title, or skill (e.g., "engineer", "sales")
company_nameYesLinkedIn company URL slug (e.g., "docker", "anthropicresearch", "microsoft")

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, but the description adds behavioral context: it derives data from a specific LinkedIn page, exposes unique demographics, and warns about fewer result pages compared to search_people. It also clarifies the slug requirement.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is multi-paragraph and detailed, but every sentence adds value—use cases, alternatives, parameter constraints, and an example. While slightly longer than strictly necessary, it's efficiently structured around purpose, usage, and uniqueness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given annotations (readOnlyHint, openWorldHint), the description covers all necessary behavioral context: output includes aggregates, page limits relative to search_people, and the surprising slug mismatch. With an output schema and both params documented, no critical gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema describes both parameters with examplesags: company_name is a slug, keywords is optional filter. The description elaborates on the slug format and gives an example, but doesn't fully detail keyword matching semantics beyond 'name, title, or skill.' Schema coverage is 100% and description reinforces it, so a high score is warranted.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource:

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly directs users to search_people for filtered searches by degree/location and notes the /people/ tab limitation, providing clear exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_company_postsGet Company PostsA
Read-only

Get recent posts from a company's LinkedIn feed.

NameRequiredDescriptionDefault
company_nameYesLinkedIn company name (e.g., "docker", "anthropic", "microsoft")

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint. The description adds no extra context about authentication, rate limits, or side effects. It does not contradict the annotations, but it also does not provide additional behavioral details beyond what the annotations already imply.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence with no unnecessary words or repetition. It is well-structured and directly states the tool's function.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple and the description sufficiently covers its purpose. Since an output schema exists (per context signals), the description does not need to explain return values, and no additional context is required for this straightforward operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides a description for the only parameter (company_name) with examples. The tool description does not add further semantic meaning beyond the schema, and since the schema coverage is high, the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('get') and the resource ('recent posts from a company's LinkedIn feed'). It effectively differentiates from sibling tools like 'get_company_profile' or 'get_company_employees' by specifying the data type (posts).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explicitly state when to use this tool versus alternatives, nor does it provide conditions or exclusions. However, the purpose is so straightforward that the usage context is implicitly clear for someone familiar with LinkedIn tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_company_profileGet Company ProfileA
Read-only

Get a specific company's LinkedIn profile.

NameRequiredDescriptionDefault
sectionsNoComma-separated list of extra sections to scrape. The about page is always included. Available sections: posts, jobs Examples: "posts", "posts,jobs" Default (None) scrapes only the about page.
company_nameYesLinkedIn company name (e.g., "docker", "anthropic", "microsoft")

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations (readOnlyHint=true, openWorldHint=true) already indicate a read-only, side-effect-free operation. The description does not contradict these hints and adds no additional behavioral detail such as rate limits or authentication requirements, which would have improved transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence that immediately conveys the tool's purpose. It is front-loaded and free of unnecessary wording, making it efficiently scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simplicity of the tool, the description is adequate. It conveys the core function, and the schema covers parameter details. However, it might slightly benefit from mentioning that it scrapes the profile (as implied in the schema), but this is not essential for basic usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides high coverage (100%) with detailed descriptions for both parameters, including examples and defaults. The description itself adds no extra meaning beyond the schema, so it does not enhance parameter understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'Get a specific company's LinkedIn profile.' It uses a specific verb ('Get') and resource ('company's LinkedIn profile'), which distinguishes it from sibling tools like get_company_posts and get_company_employees.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus the sibling tools. It does not mention any conditions or alternatives, leaving the user to infer usage from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_conversationGet ConversationA

Read a specific messaging conversation.

Provide either linkedin_username or thread_id to identify the conversation.

When looked up by linkedin_username, resolution searches the messaging inbox for the participant's display name and click-visits every matching row to capture its thread ID — LinkedIn's sidebar has no anchor hrefs or thread-id attributes, so this is the only available path. Each visit selects the row in the LinkedIn UI and may mark it as read. Pass thread_id directly to skip this enumeration.

NameRequiredDescriptionDefault
indexNo0-based selector for which thread to open when the participant has multiple threads (e.g. an organic 1-on-1 plus an InMail). Ignored when thread_id is provided. To enumerate thread IDs first, call search_conversations.
thread_idNoLinkedIn messaging thread ID
linkedin_usernameNoLinkedIn username of the conversation participant

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses that visiting UI rows 'may also mark them as read' (unusual if no read hint provided). It also explains how the UI's restrictions make enumeration necessary, and the side effect makes the agent more informed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense, layered description that explains LinkedIn UI limitations and the match between the index and thread IDs. Each sentence adds information, but it's somewhat lengthy as it packs in all behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Input schema is complete, output schema, openWorldHint, descriptions of parameter semantics, but no mention of errors, permissions, or result shape (output schema fills that). Adequate for given complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema documentation is 100% covered and describes 'index' behavior with 0-based selection and its precedence relationship to thread_id; the description of the lookup parameters adds contextual nuance beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a clear action ('read a specific conversation') and distinguishes it as one conversation by username or ID. Sibling tools like get_inbox list all messages, so the 'specific' scope is evident. It lacks explicit sibling differentiation, but the verb+object is specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the linkedin_username lookup path, what it does (enumerating rows), and when to pass thread_id directly 'to skip this enumeration'. It says it's 'the only available path' to justify behavior. No explicit alternatives list, but usage implication is strong.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_feedGet FeedA
Read-only

Get posts from the authenticated user's LinkedIn feed.

NameRequiredDescriptionDefault
num_postsNoNumber of posts to fetch (1-50, default 10). Posts are loaded in batches of ~5 as the page scrolls, so the actual count may slightly exceed the target.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description does not disclose behavioral traits beyond the annotations: it only says 'Get posts', which is consistent with readOnlyHint=true but adds no new behavioral context. Notable behavior like batched loading and count overshooting appears only in the schema property description, not in the tool description.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short sentence with no filler, front-loading the action and resource. It is concise without sacrificing clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only feed fetch with one optional parameter and an output schema, the description plus schema provide all necessary information. The feed scope is clear, and nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with the num_posts parameter fully documented including default, range, and batch behavior. The tool description itself adds no parameter detail, but the schema already carries the full semantic burden, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb 'Get' and a specific resource 'posts from the authenticated user's LinkedIn feed', which clearly distinguishes it from sibling tools like get_company_posts and search_posts. The phrase 'authenticated user' pins the scope unambiguously.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use — fetching the current user's LinkedIn feed — is reasonably implied by the description, but there is no explicit guidance about when to choose this over alternative tools such as search_posts or get_company_posts. No exclusions or routing hints are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_inboxGet InboxA
Read-only

List recent conversations from the LinkedIn messaging inbox.

NameRequiredDescriptionDefault
limitNoMaximum number of conversations to load (1-50, default 20)

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry the safety profile (readOnlyHint=true) and the volatility expectation (openWorldHint=true), lowering the bar. The description adds modest behavioral value by specifying a recency ordering and inbox scope, but it does not disclose pagination behavior or whether ordering is guaranteed beyond the word 'recent.'

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence with zero filler: the verb is front-loaded, the resource and scope are named immediately, and no structured information from the schema or annotations is redundantly repeated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list tool with one fully documented optional parameter, an output schema, and safety annotations, almost nothing an agent needs to call it is missing. The only slight gap is pinning down the meaning of 'recent' and the ordering guarantee, which is minor at this complexity level.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%: the single parameter (limit) has its type, numeric range, default, and meaning fully documented in the schema. The description contributes no parameter-level detail, so the baseline 3 for fully covered schemas applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('List') and a well-defined resource ('recent conversations from the LinkedIn messaging inbox'). It distinguishes cleanly from the sibling tools get_conversation (a single thread's messages) and search_conversations (query-driven search), so an agent can tell them apart without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description establishes clear context: this is the default, recency-ordered browsing entry point for inbox conversations. However, it never names the alternatives or states when not to use it — especially relevant given the closely related search_conversations and get_conversation siblings — so the routing decision is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_job_detailsGet Job DetailsA
Read-only

Get job details for a specific job posting on LinkedIn.

NameRequiredDescriptionDefault
job_idYesLinkedIn job ID (e.g., "4252026496", "3856789012")

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so the description does not need to restate basic safety. The description adds no meaningful behavioral context beyond the annotations, such as what kind of details are returned or whether the job must be publicly accessible. It is consistent with the annotations, so no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is one short sentence with no filler. It front-loads the action and resource, and every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity—one parameter, full schema coverage, output schema present, and read-only annotations—the description is nearly complete. The only minor gap is lack of explicit guidance on when to choose this over search_jobs, but the 'specific job posting' wording covers the core usage context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 100% coverage for the single parameter, including an example format for job_id. The description does not add additional parameter meaning beyond what the schema already provides, but with full schema coverage the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Get'), the resource ('job details'), and the scope ('for a specific job posting on LinkedIn'). It distinguishes itself from sibling tools like search_jobs and get_saved_jobs by emphasizing a specific job ID rather than searching or listing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'for a specific job posting' implies this tool should be used when you already have a job_id and need details, as opposed to searching for jobs. However, it does not explicitly state when not to use it or name alternative tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_my_profileGet My ProfileA
Read-only

Get the authenticated user's own LinkedIn profile.

Navigates to /in/me/ and resolves the redirect to obtain the real username before scraping, so the url field in the result is the actual profile URL (e.g. linkedin.com/in/johndoe/) rather than /in/me/.

NameRequiredDescriptionDefault
sectionsNoComma-separated list of extra sections to scrape. The main profile page is always included. Available sections: experience, education, interests, honors, languages, certifications, skills, projects, contact_info, posts Examples: "experience,education", "contact_info", "skills,projects" Default (None) scrapes only the main profile page.
max_scrollsNoMaximum pagination attempts per section (same as get_person_profile).

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered. The description adds valuable behavioral context by explaining that the tool navigates to /in/me/, follows the redirect, and returns the canonical profile URL instead of the /in/me/ placeholder.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose in the first sentence, and the second sentence adds a single high-value behavioral detail about redirect resolution. There is no filler, repetition of schema content, or tangential information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the low complexity, full schema coverage, and presence of an output schema, the description provides everything needed to invoke the tool correctly. The redirect-resolution note closes the only likely source of confusion about the returned url field.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the input schema already documents sections and max_scrolls with defaults, examples, and constraints. The tool description does not add additional parameter meaning, so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool gets the authenticated user's own LinkedIn profile, using a specific verb and resource. It also distinguishes itself from sibling tools like get_person_profile by emphasizing 'own' profile, and adds a concrete detail about resolving /in/me/ to the real URL.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies this tool is for the authenticated user's own profile, which differentiates it from get_person_profile. It does not explicitly name alternatives or enumerate when-not-to-use, but the context is clear enough for an agent to select it appropriately.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_person_profileGet Person ProfileA
Read-only

Get a specific person's LinkedIn profile.

NameRequiredDescriptionDefault
sectionsNoComma-separated list of extra sections to scrape. The main profile page is always included. Available sections: experience, education, interests, honors, languages, certifications, skills, projects, contact_info, posts Examples: "experience,education", "contact_info", "skills,projects", "honors,languages", "posts" Default (None) scrapes only the main profile page.
max_scrollsNoMaximum pagination attempts per section to load more content. On detail sections (experience, certifications, skills, etc.) this is the max number of "Show more" button clicks. On activity/posts it is the max scroll-to-bottom iterations. Applies to all sections in this call. Default (None) uses 5 for detail sections and 10 for posts. Increase when a profile has many items in a section (e.g., 30+ certifications, max_scrolls=20). To avoid slowing down other sections, request heavy sections in a separate call.
linkedin_usernameYesLinkedIn username (e.g., "stickerdaniel", "williamhgates")

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and openWorldHint=true, so the safety profile is clear. The description adds context about optional sections and pagination behavior (max_scrolls) which helps set expectations. It doesn't repeat annotation info, adding value on how the tool scrapes sections, though it could be more explicit about potential side effects (none) or rate limiting. Given annotations cover read-only nature, a 4 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single clear sentence, front-loaded with the action. It's concise, but it lacks detail on options that the schema covers, making it slightly under-specified as a standalone description. However, given the schema's richness, it's appropriately brief. It earns a 4 for efficiency.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a rich schema (100% param coverage) and an output schema present, the description doesn't need to explain return values. The description covers the primary purpose and the schema handles details. It is complete enough for a straightforward read operation, though it doesn't mention error scenarios. Given the annotations, a 4 is fair.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides 100% coverage of parameters with detailed descriptions (e.g., sections format, max_scrolls behavior). The description doesn't add additional parameter meaning beyond what's in the schema, so baseline 3 is justified. It does mention the main parameter implicitly in 'specific person', but that's minimal.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves a specific person's LinkedIn profile using a username, which distinguishes it from siblings like get_my_profile and get_company_profile. It is specific verb+resource with the required parameter noted.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for retrieving a profile by username, and the schema adds context on optional sections. However, it doesn't explicitly contrast with sibling tools like search_people or get_sidebar_profiles, but the purpose is clear enough for an agent to select it when a known username is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_saved_jobsGet Saved JobsA
Read-only

List job postings saved by the authenticated LinkedIn user.

Returns job_ids that can be passed to get_job_details for full info.

NameRequiredDescriptionDefault
max_pagesNoMaximum number of saved-jobs pages to load (1-10, default 3)

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations declare readOnlyHint and openWorldHint, so the safety profile is already covered. The description adds value by clarifying that the result is limited to the authenticated user's saved job postings and that it returns job_ids, not full job details—an important behavioral distinction from get_job_details. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The first sentence states the action and scope, and the second sentence provides the important downstream usage detail about feeding job_ids into get_job_details. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only list tool with one optional parameter and an output schema, the description is complete. It identifies the authenticated-user scope, the return value, and the logical next step. The annotations cover read-only and open-world behavior, and the schema covers the only parameter. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already fully documents max_pages with type, default, range, and description, so the description does not need to repeat it. The tool has only one optional parameter, and the schema coverage is 100%. The description adds no parameter-specific meaning, but none is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') and a clear resource ('job postings saved by the authenticated LinkedIn user'), which precisely distinguishes this tool from the sibling search_jobs and get_job_details. It also states the key output type (job_ids) and how they connect to another tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the right usage context: it is for the authenticated user's own saved jobs, not general job search. It also gives explicit guidance that the returned job_ids should be passed to get_job_details for full information, which effectively routes the agent to the correct follow-up tool. It does not explicitly list when not to use it, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_sidebar_profilesGet Sidebar ProfilesA
Read-only

Get profile links from sidebar recommendation sections on a LinkedIn profile page.

Extracts profiles from "More profiles for you", "Explore premium profiles", and "People you may know" sidebar sections. Follows "Show all" links to return the full list from each section. Sections that redirect to linkedin.com/premium are skipped.

NameRequiredDescriptionDefault
linkedin_usernameYesLinkedIn username of the profile page to scrape (e.g., "stickerdaniel", "williamhgates")

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation is respected—the description only retrieves data and does not imply any modification. It clearly states the actions (follows links, skips premium sections) and avoids contradicting the annotation. Since annotations already indicate read-only, the description adds value by detailing the exact procedural behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, using two sentences to convey the core function and key details. It avoids redundancy, though the first sentence is somewhat generic and could be merged with the specifics, but overall it is well-structured and to the point.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple with one input, and the description adequately explains the output (profile links) and key behaviors (following 'Show all', skipping premium). It lacks explicit error handling or edge-case mentions, but given the simplicity and absence of an output schema, it is sufficiently complete for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema fully describes the single parameter (linkedin_username) with a clear example. The description adds no additional semantic nuance beyond what is already in the schema, so the baseline of 3 applies given 100% schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool extracts profile links from specific sidebar sections, using precise section names. It distinguishes itself from sibling tools like get_person_profile or search_people by focusing on sidebar recommendations, making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for obtaining profile recommendations from a page's sidebar, but does not explicitly contrast with alternatives like get_person_profile or search_people. However, the detailed behavior (following 'Show all', skipping premium) provides implicit context for when this tool is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_companiesSearch CompaniesB
Read-only

Search for companies on LinkedIn.

NameRequiredDescriptionDefault
keywordsYesSearch keywords (e.g., "fintech", "anthropic", "electric vehicles")

Output Schema

NameRequiredDescription

No output parameters

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses no behavioral traits beyond what 'search' and 'LinkedIn' naturally imply. Annotations already declare readOnlyHint and openWorldHint, but the description adds no further context about result limits, matching behavior, or ordering. It is not contradictory, but it is also not informative beyond the basic action.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single compact sentence that wastes no words and immediately states the core action and target resource. It is appropriately sized for a simple tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter tool with an output schema and safety annotations, the description is minimally adequate. However, it does not clarify edge behavior, result scope, or how it differs from nearby company-related tools, so an agent may still need to infer intent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already fully documents the only parameter, keywords, with a useful example. The description adds no additional semantic detail beyond the schema, so a baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the verb ('Search') and resource ('companies on LinkedIn'), so an agent can understand the basic function. However, it does not differentiate itself from sibling tools like get_company_profile or search_people, leaving some ambiguity about scope or result type.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool instead of search_people, get_company_profile, or get_company_employees. The description implies keyword-based discovery but provides no explicit context, prerequisites, or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_conversationsSearch ConversationsC

Search messages by keyword.

NameRequiredDescriptionDefault
limitNoMaximum number of search-result rows to enumerate as conversation references (1-50, default 20). Each enumeration selects the row in LinkedIn's UI and may mark it as read, so a low cap is preferable for noisy queries.
keywordsYesSearch keywords to filter conversations

Output Schema

NameRequiredDescription

No output parameters

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The only annotation is openWorldHint, so the description carries most of the behavioral disclosure burden. It does not mention that enumerating results may mark conversations as read (noted only in the limit parameter description), nor does it disclose result-shaping behavior. 'Search' implies a read operation, but side effects are hidden.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single compact, front-loaded sentence with no filler. It is easy to parse, but it is so terse that it contributes little beyond the tool name and parameter names, making it less effective than it could be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with an output schema and fully described parameters, the description is minimally adequate for invocation. However, it lacks usage guidance, scope clarification, and behavioral disclosures, so an agent cannot fully judge when to use it or what side effects may occur.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema already fully documents keywords and limit. The description adds no new parameter semantics beyond restating the keyword filter; it does not provide format details, examples, or constraints beyond what the schema offers.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action (search) and resource (messages), making the tool's core purpose clear. It is somewhat distinct from sibling search tools by focusing on messages, but it does not explicitly differentiate itself from related tools like get_inbox, get_conversation, or search_posts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no guidance on when to use this tool versus alternatives such as get_inbox, get_conversation, or search_posts. There is no mention of scope, prerequisites, or situations where another tool should be preferred.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_jobsSearch JobsA
Read-only

Search for jobs on LinkedIn.

Returns job_ids that can be passed to get_job_details for full info.

NameRequiredDescriptionDefault
sort_byNoSort results (date, relevance)
job_typeNoFilter by job type, comma-separated (full_time, part_time, contract, temporary, volunteer, internship, other)
keywordsYesSearch keywords (e.g., "software engineer", "data scientist")
locationNoOptional location filter (e.g., "San Francisco", "Remote")
max_pagesNoMaximum number of result pages to load (1-10, default 3)
work_typeNoFilter by work type, comma-separated (on_site, remote, hybrid)
easy_applyNoOnly show Easy Apply jobs (default false)
date_postedNoFilter by posting date (past_hour, past_24_hours, past_week, past_month)
experience_levelNoFilter by experience level, comma-separated (internship, entry, associate, mid_senior, director, executive)

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this as read-only and open-world. The description adds value by stating that the tool returns job_ids that serve as inputs to get_job_details, which is useful contextual behavior. It does not discuss pagination, max_pages behavior, or filtering limits, but the schema covers those details.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences with no filler. The primary purpose is front-loaded, and the follow-up guidance about job_ids is immediately useful. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a search tool with a rich, fully documented schema and an output schema present, the description is sufficient: it states the purpose and the relationship to get_job_details. It does not need to explain parameters or return values in depth because those are already structured elsewhere.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the heavy lifting is already done by the input schema. The description adds no additional meaning about parameters beyond what the schema documents, matching the baseline for full schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action ('Search') on a specific resource ('jobs on LinkedIn') and adds the key behavioral result: it returns job_ids intended for get_job_details. This differentiates it from sibling search tools like search_people and search_companies.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context: use this tool when you want to search LinkedIn jobs, and use the returned IDs with get_job_details for fuller information. It does not explicitly list exclusions or compare against alternatives like get_saved_jobs, but the intended use case is obvious.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_peopleSearch PeopleA
Read-only

Search for people on LinkedIn.

NameRequiredDescriptionDefault
networkNoOptional connection-degree filter. Each element is one of "F" (1st-degree), "S" (2nd-degree), "O" (3rd-degree and beyond). Example: ["F"] to only return 1st-degree connections.
keywordsYesSearch keywords (e.g., "software engineer", "recruiter at Google")
locationNoOptional location filter (e.g., "New York", "Remote")
current_companyNoOptional current-employer filter. LinkedIn's currentCompany facet only filters on the numeric company URN id (e.g. "1115" for SAP); plain company names are accepted by the URL but ignored by LinkedIn and return the unfiltered result set. Look up a company's URN via get_company_profile -- it is exposed under references["about"]. For company-wide employee demographics (location/education/function breakdown) plus a slug-based lookup, use get_company_employees instead.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the read-only and open-world nature of this tool. The schema adds a useful caveat that plain company names are silently ignored by LinkedIn's currentCompany filter, but the main description discloses no additional behavioral traits such as result limits, pagination, or network-scope behavior. This is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence with no wasted words. It is appropriately concise, though it sacrifices useful context that could have been included without much bloat, keeping it just below a top score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The schema fully documents all parameters, annotations cover safety and open-world behavior, and an output schema exists, so the definition is mostly sufficient for invocation. The main gap is the lack of explicit sibling differentiation in the description itself, but the tool name and parameter guidance compensate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the parameters are already well documented and the baseline is 3. The tool description itself adds no parameter-level meaning. The detailed current_company guidance lives in the schema, not in the description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a verb and resource: it searches for people on LinkedIn. This distinguishes it from other search tools like search_companies and search_jobs, though it does not explicitly contrast it with person-related siblings such as get_sidebar_profiles or get_person_profile.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description establishes a clear use case: finding people. The current_company parameter description adds valuable routing guidance, directing agents to get_company_profile for URN lookup and get_company_employees for company-wide demographics. However, the tool description itself does not provide a broader when-not-to-use statement versus other people lookup tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_postsSearch PostsA
Read-only

Search LinkedIn posts/content globally by keyword (the "Posts" tab).

Use this to catch informal hiring posts ("we're hiring", "Buscamos ...", "estamos contratando", "join our team") that often appear before a formal job listing exists. This is global content search, distinct from get_feed (your own home feed) and get_company_posts (one company's page).

NameRequiredDescriptionDefault
keywordsYesSearch keywords (e.g., "Buscamos Unity", "AI automation hiring")
max_pagesNoScroll depth as result "pages" of ~5 scrolls each (1-10, default 3). Content search is an infinite scroll, so this caps how far the page is scrolled rather than fetching discrete pages.
date_postedNoOptional recency filter. One of "past-24h", "past-week", "past-month"; the "past_24_hours" / "past_week" / "past_month" spellings used by search_jobs are accepted too. Omit for any time.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With readOnlyHint and openWorldHint already present, the description adds useful context: this is a global content search, not a feed or company-scoped search. It also implies results may include informal/unofficial hiring language, which is relevant behavioral context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: one sentence defines the action, the next gives a concrete use case, and the final sentence distinguishes it from siblings. Every sentence earns its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the 100% parameter schema coverage, the presence of an output schema, and annotations covering safety and openness, the description covers all essential decision factors. It tells the agent what the tool does, when to use it, what alternatives exist, and how to craft effective queries.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value by providing richer keyword examples and clarifying that content search is global rather than scoped, supplementing the schema's parameter descriptions. It meaningfully supports keyword selection without redundancy.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb and resource: 'Search LinkedIn posts/content globally by keyword.' It also explicitly differentiates itself from get_feed and get_company_posts, so an agent can immediately identify what this tool is and what it is not.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a concrete use case—catching informal hiring posts before formal job listings exist—and provides example keyword patterns. It also names the two sibling alternatives and explains why they are different, making the selection decision explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_messageSend MessageA
Destructive

Send a message to a LinkedIn user.

The recipient must be directly messageable from the profile page. This is a write operation when confirm_send is True.

NameRequiredDescriptionDefault
messageYesThe message text to send
profile_urnNoOptional profile URN (e.g. ACoAAB...) to construct the compose URL directly. Providing this bypasses the Message-button lookup and is more reliable when available. Obtain via get_person_profile. Note: inbox may not always show all messages; use search_conversations as a fallback.
confirm_sendYesMust be True to send the message
linkedin_usernameYesLinkedIn username of the recipient

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (destructiveHint and openWorldHint), the description clarifies that the write happens only when confirm_send is True, which is a safeguard. It also adds the requirement for direct messageability. This extra context helps the agent understand the tool's behavior without relying solely on annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: two sentences that immediately state the purpose and key constraint. It front-loads the core function and avoids unnecessary elaboration, making it easy for an agent to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a write operation, the description covers the essential behavioral prerequisites (messageability, confirm_send flag) and relies on the schema for parameter details. It does not mention authentication or output, but those are supplied by annotations and the presence of an output schema. The description is adequate for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides complete descriptions for all four parameters (100% coverage), so the tool description does not need to repeat them. It does not add any additional meaning beyond what the schema gives, which is the baseline expectation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (send) and target (a LinkedIn user), with an important qualifier about direct messageability from the profile page. This establishes the tool's core purpose and differentiates it from read-only LinkedIn tools by explicitly labeling it a write operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a prerequisite (the recipient must be directly messageable) and notes that the send only occurs when confirm_send is True, implicitly advising caution. However, it does not mention when to choose this tool over alternatives like connecting first or using the inbox, so guidance on context and exclusions is limited.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 19 tool updatesv4.22.0
    • First observedclose_session
    • First observedconnect_with_person
    • First observedget_company_employees
    • First observedget_company_posts
    • First observedget_company_profile
    • First observedget_conversation
    • First observedget_feed
    • First observedget_inbox
    • First observedget_job_details
    • First observedget_my_profile
    • First observedget_person_profile
    • First observedget_saved_jobs
    • First observedget_sidebar_profiles
    • First observedsearch_companies
    • First observedsearch_conversations
    • First observedsearch_jobs
    • First observedsearch_people
    • First observedsearch_posts
    • First observedsend_message

TDQS

A3.8/5.0

Scored across 19 tools

Disambiguation5/5

Each tool targets a distinct resource/action: people, companies, jobs, messaging, feed, and session management. Overlapping tools like get_feed/search_posts/get_company_posts and get_company_employees/search_people are explicitly differentiated in their descriptions, so an agent should not misselect.

Naming Consistency5/5

All tool names follow a verb_noun snake_case pattern, primarily get_* and search_*, with a few clear action verbs like send_message, connect_with_person, and close_session. The naming is predictable and consistent across the full set.

Tool Count3/5

At 19 tools, the server is in the 16-25 range that feels heavy, even though the LinkedIn domain is broad. Some niche helpers like get_sidebar_profiles and close_session could be considered non-essential, but the count is not extreme enough to be chaotic.

Completeness4/5

Core workflows are covered end-to-end: search people, companies, and jobs; retrieve details; connect; message; and read feeds/inbox. Obvious gaps are modest, such as no ability to post content, manage connections, or apply to jobs, but these are not central to the apparent sales/recruiting use case.

Maintenance

ActivityStale
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI assistants to securely search your LinkedIn network, contacts, and DMs to find warm leads, intro paths, and hidden opportunities.
    32
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI assistants to browse profiles and companies, manage messages and inboxes, and search jobs, posts, and people through a locally logged-in browser session. All actions run on the user's own machine.
    19
    Apache 2.0