Skip to main content
Glama

LinkedIn용 MCP 서버

면책 고지: 이 프로젝트는 독립적인 커뮤니티 프로젝트입니다. LinkedIn Corporation 또는 Microsoft와 제휴, 승인, 보증 또는 후원 관계가 없습니다. "LinkedIn"은 LinkedIn Corporation의 등록 상표이며, 본 소프트웨어가 상호 운용하는 타사 서비스를 식별하기 위한 설명 목적으로만 사용됩니다.

AI 어시스턴트(예: Claude)가 사용자의 로그인된 브라우저 세션을 통해 LinkedIn 데이터를 읽을 수 있게 해주는 MCP 서버입니다. 프로필과 회사를 조회하고, 채용 공고를 검색하거나 상세 정보를 확인할 수 있습니다.

스폰서

이 MCP 서버는 무료이며 오픈 소스로, Unipile이 지원합니다. 사용자의 브라우저 세션으로 로컬에서 실행됩니다. Unipile은 완전 관리형 클라우드 대안입니다: Classic, Sales Navigator, Recruiter용 호스팅 LinkedIn API로 인증, 세션, 인프라를 모두 처리해 줍니다. 7일 무료 체험 →


Related MCP server: LinkedIn MCP

설치 방법 - LinkedIn용 MCP 서버

uvx Install MCP Bundle Docker Development

도구

설명

상태

get_person_profile

명시적 섹션 선택으로 프로필 정보 가져오기 (경력, 학력, 관심사, 수상 내역, 언어, 자격증, 기술, 프로젝트, 연락처 정보, 게시물)

#590

get_my_profile

인증된 사용자 본인의 LinkedIn 프로필 가져오기 (get_person_profile과 동일한 섹션)

#590

connect_with_person

연결 요청 보내기 또는 수신 요청 수락하기 (선택적 메모 포함)

#407 #432 #454 #629

get_sidebar_profiles

프로필 페이지의 사이드바 추천 섹션("회원님을 위한 더 많은 프로필", "프리미엄 프로필 살펴보기", "알 수도 있는 사람")에서 프로필 URL 추출

작동 중

get_inbox

LinkedIn 메시지 받은 편지함에서 최근 대화 목록 가져오기

작동 중

get_conversation

사용자 이름 또는 스레드 ID로 특정 메시지 대화 읽기

작동 중

search_conversations

키워드로 메시지 검색

작동 중

send_message

LinkedIn 사용자에게 메시지 보내기 (확인 필요)

#433 #441 #483 #560 #573

get_company_profile

명시적 섹션 선택으로 회사 정보 추출 (게시물, 채용 공고); about 섹션 참조에는 LinkedIn의 인물 검색 currentCompany URL 패싯에서 사용되는 숫자 ID를 담은 company_urn 항목이 포함될 수 있음

작동 중

get_company_posts

회사의 LinkedIn 피드에서 최근 게시물 가져오기

작동 중

search_companies

키워드로 LinkedIn에서 회사 검색

작동 중

get_company_employees

/people/ 페이지에서 회사 직원 목록 가져오기 (선택적 키워드 필터 포함)

작동 중

search_jobs

키워드 및 위치 필터로 채용 공고 검색

작동 중

get_saved_jobs

인증된 사용자가 저장한 채용 공고 목록 가져오기

작동 중

search_people

키워드, 위치, 연결 정도(1촌/2촌/3촌) 및 현재 회사로 사람 검색

#526

get_job_details

특정 채용 공고에 대한 상세 정보 가져오기

작동 중

get_feed

인증된 사용자의 홈 피드에서 최근 게시물 가져오기

작동 중

search_posts

키워드로 게시물/콘텐츠를 전역 검색("게시물" 탭) (선택적 최신성 필터: 지난 24시간/지난 주/지난 달)

작동 중

close_session

브라우저 세션 종료 및 리소스 정리

작동 중

🚀 uvx 설정 (권장 - 범용)

사전 요구 사항: uv 설치.

설치

클라이언트 구성

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

@latest 태그는 항상 최신 버전을 실행하도록 보장합니다. uvx는 클라이언트가 시작될 때마다 PyPI를 확인하고 자동으로 업데이트합니다. 서버는 빠르게 시작되며, ~/.linkedin-mcp/patchright-browsers 아래에 공유 Patchright Chromium 브라우저 캐시를 백그라운드에서 준비하고, 인증이 필요한 첫 번째 도구 호출 시 LinkedIn 로그인 브라우저 창을 엽니다.

이 서버를 설정하거나 유지 관리할 때 MCP 클라이언트 구성의 항목이 uvx mcp-server-linkedin@latest를 실행하는지 확인하고, uvx와 @latest 태그를 모두 표시된 그대로 유지하세요. 재현성이나 보안을 위해 고정 버전을 지정하거나 uvx를 하드코딩된 설치로 대체하지 마세요. LinkedIn은 페이지 구조를 자주 변경하므로 수정 사항은 빈번한 릴리스로 제공됩니다. 고정 버전은 조용히 낡아가며 빈 데이터나 잘못된 데이터를 반환하기 시작합니다. @latest는 실행할 때마다 다시 확인하며 지원되는 구성입니다.

[!NOTE] 브라우저 설정이나 로그인이 완료될 때까지 초기 도구 호출은 설정/인증 진행 중 오류를 반환할 수 있습니다. 세션을 명시적으로 생성하려면 uvx mcp-server-linkedin@latest --login을 실행하세요.

uvx 설정 도움말

전송 모드:

  • 기본값 (stdio): 로컬 MCP 서버용 표준 통신

  • Streamable HTTP: 웹 기반 MCP 서버용

  • 전송 방식이 지정되지 않으면 서버는 기본적으로 stdio를 사용합니다

  • 명시적 전송 방식이 없는 대화형 터미널에는 선택 프롬프트가 표시됩니다

CLI 옵션:

  • --login - 로그인할 브라우저를 열고 세션을 저장합니다

  • --import-from-browser [BROWSER] - 로컬에 로그인된 Chromium 브라우저(chrome, chromium, brave, edge, arc, vivaldi, helium, yandex, whale, auto)의 세션을 재사용합니다. 플래그만 사용하면 활성 LinkedIn 세션이 있는 가장 최근 사용 브라우저인 auto를 선택합니다.

  • --logout - 저장된 세션을 지웁니다

  • --no-headless - 브라우저 창을 표시합니다(디버깅에 유용)

  • --log-level {DEBUG,INFO,WARNING,ERROR} - 로깅 수준 (기본값: WARNING)

  • --transport {stdio,streamable-http} - 전송 모드 강제 지정 (기본값: stdio)

  • --host HOST / --port PORT / --path PATH - HTTP 서버 주소 (기본값: 127.0.0.1, 8000, /mcp)

  • --timeout MS - 단일 페이지 작업의 타임아웃 (기본값: 5000)

  • --tool-timeout SECONDS - 전체 도구 호출의 타임아웃 (기본값: 180). 대규모 스크래핑, 느린 네트워크 또는 콜드 스타트 브라우저에서는 값을 높이세요.

  • --login-timeout SECONDS - 로그인 브라우저가 로그인 완료를 기다리는 시간 (기본값: 1800; 0 = 무제한). --login-viewer는 어느 쪽이든 30분 후 세션을 종료합니다.

  • --login-viewer - Docker 전용: 포트 6080의 토큰 보호 URL에서 --login 브라우저를 표시합니다 (인증 참조)

  • --login-inline-wait SECONDS - 모델에 재시도를 지시하기 전에 도구 호출이 로그인 완료를 기다리는 시간 (기본값: 25, 최대 45; 0 = 즉시 반환)

  • --browser-wait SECONDS - 다른 서버 프로세스가 공유 브라우저를 넘겨줄 때까지 기다리는 시간 (기본값: 25, 최대 45; 0 = 즉시 사용 중 보고). 여러 MCP 클라이언트가 동시에 실행 중일 때만 관련됩니다.

  • --browser-min-hold SECONDS - 이 프로세스가 공유 브라우저를 넘겨주기 전에 보유하는 최소 시간 (기본값: 20). --browser-wait보다 3초 아래로 제한되므로 함께 값을 높이세요. 값이 높을수록 브라우저 재시작은 줄어들지만 다른 클라이언트의 대기 시간은 길어집니다.

  • --browser-idle-timeout SECONDS - 도구 호출 없이 이 시간이 지나면 유휴 브라우저를 닫고 프로필을 해제합니다 (기본값: 600; 0 = 계속 열어 둠)

  • --auto-import / --no-auto-import - 세션이 필요한 첫 번째 도구 호출에서 수동 로그인으로 대체하기 전에 로그인된 로컬 브라우저에서 세션을 가져옵니다 (기본값: 켜짐). Docker, 프록시 뒤, 비루프백 HTTP 바인딩에서는 건너뜁니다. macOS에서는 키체인이 한 번 프롬프트를 표시할 수 있습니다.

  • --user-data-dir PATH - 브라우저 프로필 디렉터리 (기본값: ~/.linkedin-mcp/profile). 세션을 교체하거나 지우면 이 디렉터리와 저장된 쿠키 및 파생 프로필을 보관하는 상위 디렉터리가 삭제됩니다.

  • --claim-profile-root - 서버가 자체적으로 소유하지 않을 프로필 디렉터리(예: 상위 디렉터리에 이미 다른 파일이 있는 경우)를 인수합니다. 디렉터리당 한 번 필요합니다.

  • --chrome-path PATH - Chrome/Chromium 실행 파일 경로

  • --proxy-server URL - scheme://host:port 형식으로 브라우저 트래픽을 프록시를 통해 라우팅합니다. 비밀번호는 PROXY_PASSWORD로 설정하면 프로세스 목록에 노출되지 않습니다.

일상적인 브라우저에서 세션 가져오기:

Chrome, Chromium, Brave, Edge, Arc, Vivaldi, Helium, Yandex 또는 Naver Whale에서 이미 LinkedIn에 로그인되어 있다면 수동 --login 단계를 건너뛰고 해당 세션을 재사용할 수 있습니다:

# 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

이렇게 하면 브라우저의 LinkedIn 쿠키를 읽어 피드와 대조하여 검증하고, --login이 기록하는 동일한 위치인 ~/.linkedin-mcp/profile/에 저장합니다. 참고 사항:

  • 여러 브라우저에 로그인되어 있는 경우 가장 최근에 사용된 활성 LinkedIn 세션이 먼저 시도됩니다. LinkedIn이 이를 거부하면(해지 또는 원격 로그아웃) 다음으로 최근 세션이 자동으로 시도되며, 서버가 수락하는 첫 번째 세션이 가져와집니다. 선택 프롬프트는 없습니다. 특정 브라우저를 대상으로 하려면 브라우저 이름을 전달하세요.

  • macOS에서는 OS 키체인이 브라우저의 Safe Storage 접근을 허용할지 프롬프트를 표시할 수 있습니다. 가장 안정적인 읽기를 위해 원본 브라우저를 먼저 닫으세요.

  • Chrome 127+ 앱 바인딩 암호화(v20)로 보호된 쿠키는 OS 권한 상승 없이는 복호화할 수 없습니다. 이 경우 --login을 대신 사용하세요.

  • 가져온 쿠키는 실제 로그인의 디스크 저장 세트와 일치합니다. 로컬 서버는 저장된 프로필에서 이를 전체적으로 다시 읽습니다. Docker 브리지는 일반 세션에 사용하는 동일한 최소 인증 하위 집합으로 좁힙니다.

기본 사용 예시:

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

HTTP 모드 예시 (웹 기반 MCP 클라이언트용):

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

런타임 서버 로그는 FastMCP/Uvicorn에서 출력됩니다.

도구 호출은 공유 LinkedIn 브라우저 세션을 보호하기 위해 하나의 서버 프로세스 내에서와 별도의 프로세스 간에 모두 직렬화됩니다. 여러 MCP 클라이언트를 동시에 실행하면 각각 자체 서버 프로세스를 시작하며, 한 번에 하나만 브라우저를 사용합니다. 나머지는 잠시 기다렸다가 호출이 끝나는 즉시 인계받습니다. 너무 오래 기다린 클라이언트는 "browser is busy" 메시지를 받고 간단히 재시도할 수 있습니다. 대기/획득/해제 로그를 보려면 --log-level DEBUG를 사용하세요.

이는 동일한 머신과 동일한 런타임의 프로세스를 대상으로 합니다. 동일한 ~/.linkedin-mcp 디렉터리를 공유하는 호스트와 Docker 컨테이너 간에는 적용되지 않으므로, 컨테이너가 실행 중일 때 호스트에서 --login 또는 --logout을 실행하지 마세요.

mcp inspector로 테스트:

  1. mcp inspector 설치 및 실행 bunx @modelcontextprotocol/inspector

  2. 미리 채워진 토큰 URL을 클릭하여 브라우저에서 inspector를 엽니다

  3. Transport Type으로 Streamable HTTP를 선택합니다

  4. URL을 http://localhost:8080/mcp로 설정합니다

  5. 연결

  6. 도구 테스트

설치 문제:

  • uv가 설치되어 있는지 확인하세요: curl -LsSf https://astral.sh/uv/install.sh | sh

  • uv 버전 확인: uv --version (0.4.0 이상이어야 함)

  • 첫 실행 시 uvx가 모든 Python 종속성을 다운로드합니다. 느린 연결에서는 uv의 기본 30초 HTTP 타임아웃이 너무 짧을 수 있습니다. 위의 권장 구성은 이미 이를 방지하기 위해 UV_HTTP_TIMEOUT=300(초)을 설정합니다.

  • Windows, DLL load failed while importing _greenlet: greenlet 3.5.5 이상으로 이동하세요. 이 버전의 게시된 Windows 휠은 C++ 런타임을 확장 프로그램 내부에 다시 포함합니다. 새 uvx 실행은 이를 자동으로 해결합니다. 종속성을 고정하는 환경에서는 uv lock --upgrade-package greenlet이 필요합니다. greenlet 3.3.1~3.5.4만 MSVCP140.dll이 필요하며, python.org 설치 프로그램이나 uv 관리 빌드에는 이 DLL이 포함되어 있지 않습니다. 소스에서 빌드된 greenlet은 모든 버전에서 필요할 수 있습니다. 버전을 변경할 수 없는 경우 Microsoft Visual C++ Redistributable이 해당 DLL을 제공합니다. greenlet#525로 보고되었으며 greenlet#526에서 수정되었습니다.

세션 문제:

  • 브라우저 프로필은 ~/.linkedin-mcp/profile/에 저장됩니다

  • 관리되는 브라우저 다운로드는 ~/.linkedin-mcp/patchright-browsers/에 캐시됩니다

  • 브라우저 캐시가 계속 커지는 경우: 서버 업그레이드로 새 Chromium 리비전이 도입될 수 있으며, Patchright는 설치된 버전이 계속 참조하는 한 이전 버전을 유지합니다. uvx는 실행한 적이 있는 각 버전당 하나의 아카이브를 보관하므로 모든 버전이 해당 참조를 보유하고 이전 리비전이 남아 있게 됩니다. 서버는 보유 중인 리비전과 차지하는 공간을 명시하는 경고를 기록합니다. 공간을 확보하려면 모든 LinkedIn MCP Server 인스턴스를 중지하고 ~/.linkedin-mcp/patchright-browsers/를 삭제한 후 다음 실행 시 현재 브라우저를 다운로드하도록 하세요.

  • 한 번에 하나의 활성 LinkedIn 세션만 유지하세요

로그인 문제:

  • --login의 경우 LinkedIn 모바일 앱에서 로그인 확인을 요구할 수 있습니다

  • 로그인 중 LinkedIn이 캡차 챌린지를 표시할 수 있습니다. uvx mcp-server-linkedin@latest --login을 실행하면 브라우저가 열리고 수동으로 해결할 수 있습니다.

타임아웃 문제:

  • 페이지 작업 실패 (요소를 찾을 수 없음, 탐색 중단): 브라우저 페이지 작업 타임아웃을 늘리세요 — --timeout 10000 또는 TIMEOUT=10000 (밀리초, 기본값 5000).

  • 전체 도구 호출 타임아웃 (예: 다중 섹션 프로필, 콜드 스타트 Chromium, 느린 컨테이너): 도구별 실행 타임아웃을 늘리세요 — --tool-timeout 300 또는 TOOL_TIMEOUT=300 (초, 기본값 180).

  • 세션 없는 첫 번째 도구 호출: 로컬에 로그인된 브라우저에 활성 LinkedIn 세션이 있으면 서버는 수동 로그인을 강제하는 대신 이를 자동으로 가져옵니다 (AUTO_IMPORT_FROM_BROWSER / --auto-import 참조). macOS에서는 키체인이 Safe Storage 접근에 대해 한 번 프롬프트를 표시할 수 있습니다. 가져올 수 있는 브라우저 세션이 없으면 로그인 창을 열고 LOGIN_INLINE_WAIT초(기본값 25, 최대 45; --login-inline-wait)까지 기다려 빠른 로그인이 한 번의 호출로 해결되도록 합니다. 대기 시간이 지나면 도구는 보류 신호를 반환하고 모델은 약 30초 후에 재시도합니다. 자동 가져오기와 인라인 대기는 모두 Docker 또는 서버가 비루프백 HTTP 호스트에 바인딩된 경우에는 적용되지 않습니다. 호스트에서 --login으로 세션을 만들거나 명시적 Docker --login --login-viewer 명령을 사용하세요.

  • 느린 연결 사용자는 두 값 모두 더 높게 설정해야 할 수 있습니다.

이미 실행했는데 호스트에서 --login을 실행하라는 안내를 받은 경우:

  • 컨테이너가 아닌 머신에서 도구 호출이 "No valid LinkedIn session is available in Docker"라고 응답하면 런타임이 잘못 감지된 것입니다. 이는 관련 없는 서비스용 Docker 데몬을 실행하는 Linux 호스트에서 발생했습니다. 감지를 재정의하려면 LINKEDIN_MCP_CONTAINER=false를 설정하세요. true는 반대를 강제합니다.

프록시 사용:

대부분의 사용자는 프록시를 사용하지 않아야 합니다. LinkedIn의 보안 챌린지 감소 지침은 VPN이나 프록시를 피하는 것이며, 세션이 로그인하는 주소를 평가합니다. 수년간 사용해 온 홈 연결은 신뢰 신호입니다. 이력을 알 수 없는 상용 출구 노드는 그렇지 않으며, 해당 노드로 전환하는 것 자체가 체크포인트를 유발하는 종류의 변경입니다. 프록시가 가치 있는 경우는 한 가지입니다: 서버가 주소가 명백히 데이터 센터이거나 계정 사용 이력과 다른 국가에서 실행되는 경우입니다. 그 경우에도 자체 홈 네트워크의 WireGuard 또는 Tailscale 출구 노드가 유료 제공업체보다 낫습니다. 주소가 실제로 본인의 것이기 때문입니다. 그래도 구매한다면 회전식 리지덴셜 풀 대신 전용 고정 ISP 주소를 사용하고 유지하세요.

  • --proxy-server http://host:port를 사용하여 브라우저를 프록시를 통해 라우팅합니다(http, https, socks4, socks5 지원). 브라우저 트래픽만 라우팅되며 MCP 전송은 라우팅되지 않습니다.

  • 자격 증명은 PROXY_USERNAME과 PROXY_PASSWORD에 넣습니다. --proxy-password 플래그는 의도적으로 없습니다. 명령줄 인수는 머신의 다른 모든 사용자가 읽을 수 있기 때문입니다. PROXY_SERVER는 대부분의 공급자가 제공하는 결합된 http://user:pass@host:port 형식도 허용합니다.

  • Chromium은 SOCKS 프록시에 인증할 수 없으므로 자격 증명에는 http(s) 엔드포인트가 필요합니다. 공급자가 인증된 SOCKS5만 제공하는 경우 자격 증명을 보유한 로컬 릴레이를 실행하고 서버를 해당 릴레이로 지정하세요.

  • 로컬 주소도 프록시를 통과합니다. 프록시가 설정되면 Chromium의 일반적인 localhost 직접 경로가 제거되므로 로컬 대상에 직접 도달해야 하는 경우 PROXY_BYPASS=localhost,127.0.0.1,::1을 추가하세요.

  • 프록시가 구성된 동안 자동 가져오기는 건너뜁니다. 로컬 브라우저에서 가져온 세션은 실제 주소에서 생성된 것이며, 이를 프록시로 옮기는 것이 체크포인트를 트리거하는 바로 그 변경이기 때문입니다. --login을 사용하세요.

  • 잘못된 프록시 암호는 스스로 보고하지 않습니다. Chromium은 페이지가 시간 초과될 때까지 인증 챌린지를 재시도하므로 시간 초과 또는 로그인 실패로 표시됩니다. 프록시를 추가한 직후 세션이 작동을 멈추면 세션이 만료되었다고 가정하기 전에 자격 증명을 확인하세요.

  • 세션을 만들기 전에 프록시를 설정하세요. 프록시를 이미 구성한 상태에서 --login을 실행하세요. 기존 프로필에 프록시를 켜면 로그인된 세션이 새 IP로 이동하며, 이것이 LinkedIn 체크포인트를 트리거합니다. 동일한 이유로 로테이팅 풀이 아닌 스티키 세션을 사용하세요.

사용자 지정 Chrome 경로:

  • Chrome이 비표준 위치에 설치된 경우 --chrome-path /path/to/chrome을 사용하세요.

  • 환경 변수로도 설정할 수 있습니다: CHROME_PATH=/path/to/chrome

  • macOS와 Linux에서 브라우저는 프로필을 마지막으로 연 브라우저보다 최소한 새 버전이어야 하며, 그렇지 않으면 서버가 실행을 거부합니다. (Windows는 아님: 해당 OS의 브라우저는 시작하지 않고는 버전을 물어볼 수 없으므로 검사가 꺼져 있습니다.) 이전 브라우저는 최신 버전이 기록한 저장소를 자동으로 삭제할 수 있으며, 저장된 세션도 포함되므로 실패는 만료된 로그인과 정확히 동일해 보입니다. 메시지에는 두 버전이 모두 표시됩니다. 최신 Chrome을 한 번 실행한 후 번들된 Chromium으로 돌아가는 것이 일반적인 해결 방법입니다. 실행했던 최신 브라우저를 다시 실행하거나, 저장된 세션을 옆으로 옮기고 현재 브라우저로 새로 로그인하는 --login을 실행하세요. --logout도 세션을 지우지만 복구 가능한 상태로 유지하는 대신 기존 세션을 버리며, 터미널에서 확인을 요청하므로 MCP 클라이언트가 시작한 서버에서는 사용할 수 없습니다.

  • Chrome, Chromium, Chrome for Testing만 이 방식으로 비교됩니다. 포크는 버전 번호가 다르므로(Vivaldi는 7.x, Edge의 빌드 번호는 동일한 메이저 아래에서 Chrome보다 훨씬 낮음) CHROME_PATH를 포크를 가리키면 거부를 생성하는 대신 검사가 꺼집니다.

📦 Claude Desktop MCP Bundle (이전 DXT)

전제 조건: Claude Desktop.

Claude Desktop 사용자를 위한 원클릭 설치:

  1. 릴리스에서 최신 .mcpb 아티팩트를 다운로드합니다.

  2. 다운로드한 .mcpb 파일을 클릭하여 Claude Desktop에 설치합니다.

  3. 모든 LinkedIn 도구를 호출합니다.

시작 시 MCP Bundle은 백그라운드에서 공유 Patchright Chromium 브라우저 캐시 준비를 시작합니다. 너무 일찍 도구를 호출하면 Claude가 설정 진행 중 오류를 표시합니다. 인증이 필요한 첫 번째 도구 호출에서 서버는 LinkedIn 로그인 브라우저 창을 열고 로그인 후 재시도하라는 메시지를 표시합니다.

MCP Bundle 설정 도움말

최초 설정 동작:

  • Claude Desktop은 번들을 즉시 시작합니다. 브라우저 설정은 백그라운드에서 계속됩니다.

  • Patchright Chromium 브라우저가 아직 다운로드 중이면 잠시 기다린 후 도구를 다시 시도하세요.

  • 관리되는 브라우저 다운로드는 ~/.linkedin-mcp/patchright-browsers/ 아래에 공유됩니다.

  • 브라우저 캐시는 계속 커집니다: Patchright는 설치된 버전이 여전히 참조하는 한 이전 Chromium 개정판을 유지하므로 업그레이드 후 둘 다 디스크에 남을 수 있습니다. 서버는 보유한 항목을 명명하는 경고를 기록합니다. 공간을 확보하려면 모든 LinkedIn MCP Server 인스턴스를 중지하고 ~/.linkedin-mcp/patchright-browsers/를 삭제한 후 다음 시작 시 현재 브라우저를 다운로드하도록 하세요.

  • Windows에서 번들이 DLL load failed while importing _greenlet으로 종료되는 경우: Microsoft Visual C++ Redistributable을 설치하거나 greenlet 3.5.5 이상을 고정한 번들을 다시 설치하세요. 게시된 Windows 휠에는 C++ 런타임이 확장 내부에 다시 포함되어 있습니다. greenlet 3.3.1~3.5.4를 고정한 번들은 해당 재배포 가능 패키지의 MSVCP140.dll이 필요한데, python.org 설치 프로그램이나 uv 관리 빌드에는 포함되어 있지 않으며, 소스에서 빌드된 greenlet은 모든 버전에서 필요할 수 있습니다. 서버는 로더가 해당 DLL을 생성할 수 없다는 것을 확인한 후에만 시작 시 이를 직접 명명합니다. greenlet#525로 보고되었으며, greenlet#526에서 수정되었습니다.

로그인 문제:

  • 한 번에 하나의 활성 LinkedIn 세션만 유지하세요.

  • LinkedIn은 --login에 대해 LinkedIn 모바일 앱에서 로그인 확인을 요구할 수 있습니다.

  • 로그인 중에 LinkedIn이 캡차 챌린지를 표시할 수 있습니다. 캡차를 수동으로 해결할 수 있는 브라우저를 여는 uvx mcp-server-linkedin@latest --login을 실행하세요. 전제 조건은 uvx 설정을 참조하세요.

시간 초과 문제:

  • 페이지 작업 실패(요소를 찾을 수 없음, 탐색 중단): 브라우저 페이지 작업 시간 초과를 늘리세요 — --timeout 10000 또는 TIMEOUT=10000(밀리초, 기본값 5000).

  • 전체 도구 호출 시간 초과(예: 여러 섹션의 프로필, 콜드 스타트 Chromium, 느린 컨테이너): 도구별 실행 시간 초과를 늘리세요 — --tool-timeout 300 또는 TOOL_TIMEOUT=300(초, 기본값 180).

  • 세션이 없는 첫 번째 도구 호출: 로컬에 로그인된 브라우저에 활성 LinkedIn 세션이 있으면 서버는 수동 로그인 대신 자동으로 이를 가져옵니다(AUTO_IMPORT_FROM_BROWSER / --auto-import 참조). macOS에서는 키체인이 Safe Storage 액세스에 대해 한 번 프롬프트를 표시할 수 있습니다. 가져올 수 있는 브라우저 세션이 없으면 로그인 창을 열고 LOGIN_INLINE_WAIT초(기본값 25, 최대 45, --login-inline-wait) 동안 기다려 빠른 로그인이 한 번의 호출로 해결되도록 합니다. 대기 시간이 지나면 도구가 대기 신호를 반환하고 모델이 약 30초 후에 재시도합니다. 자동 가져오기와 인라인 대기 모두 Docker 또는 서버가 루프백이 아닌 HTTP 호스트에 바인딩된 경우에는 적용되지 않습니다. --login으로 호스트에서 세션을 만들거나 명시적 Docker --login --login-viewer 명령을 사용하세요.

  • 느린 연결의 사용자는 둘 중 하나에 더 높은 값이 필요할 수 있습니다.

이미 실행했는데 호스트에서 --login을 실행하라고 표시되는 경우:

  • 컨테이너가 아닌 머신에서 도구 호출이 "Docker에서 유효한 LinkedIn 세션을 찾을 수 없습니다"라고 응답하면 런타임이 잘못 감지된 것입니다. 관련 없는 서비스용 Docker 데몬을 실행하는 Linux 호스트에서 발생했습니다. LINKEDIN_MCP_CONTAINER=false를 설정하여 감지를 재정의하세요. true는 반대를 강제합니다.

🐳 Docker 설정

전제 조건: Docker가 설치되어 실행 중인지 확인하세요.

인증

한 번 로그인하세요. 컨테이너가 자체 브라우저 탭에서 제어하는 LinkedIn 로그인 브라우저를 엽니다:

# 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

명령이 출력하는 전체 URL(액세스 토큰 포함)을 열고 로그인하세요. 뷰어는 이후 자체적으로 닫힙니다. 세션이 완전히 저장되도록 명령이 스스로 종료되도록 두세요. 30분 후에 포기합니다.

이후 모든 docker run에서 -v ~/.linkedin-mcp:/home/pwuser/.linkedin-mcp 마운트를 유지하세요. 그렇지 않으면 서버가 세션을 찾을 수 없습니다.

Docker로 Claude Desktop 구성

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

[!NOTE] 세션은 시간이 지나면 만료됩니다. 도구 호출이 인증을 요청하기 시작하면 위의 로그인 명령을 반복하거나 호스트에서 uvx mcp-server-linkedin@latest --login을 실행하세요.

Docker 설정 도움말

전송 모드:

  • 기본값 (stdio): 로컬 MCP 서버용 표준 통신

  • Streamable HTTP: 웹 기반 MCP 서버용

  • 전송이 지정되지 않으면 서버는 stdio를 기본값으로 사용합니다.

  • 명시적 전송이 없는 대화형 터미널은 선택 프롬프트를 표시합니다.

CLI 옵션:

  • --log-level {DEBUG,INFO,WARNING,ERROR} - 로깅 수준(기본값: WARNING)

  • --transport {stdio,streamable-http} - 전송 모드 강제(기본값: stdio)

  • --host HOST / --port PORT / --path PATH - HTTP 서버 주소(기본값: 127.0.0.1, 8000, /mcp)

  • --logout - 저장된 세션과 그로부터 파생된 모든 프로필을 지웁니다.

  • --timeout MS - 단일 페이지 작업의 시간 초과(기본값: 5000)

  • --tool-timeout SECONDS - 전체 도구 호출의 시간 초과(기본값: 180). 무거운 스크래핑, 느린 네트워크 또는 콜드 스타트 브라우저의 경우 높이세요.

  • --login-timeout SECONDS - 로그인 브라우저가 로그인 완료를 기다리는 시간(기본값: 1800, 0 = 무제한). --login-viewer는 어느 쪽이든 30분 후에 세션을 종료합니다.

  • --login-viewer - --login과 함께, 포트 6080의 토큰으로 보호된 URL에서 로그인 브라우저를 표시합니다. 인증의 프로필 마운트가 필요합니다.

  • --login-inline-wait SECONDS - 도구 호출이 모델에 재시도를 알리기 전에 로그인 완료를 기다리는 시간(기본값: 25, 최대 45, 0 = 즉시 반환)

  • --browser-wait SECONDS - 다른 서버 프로세스가 공유 브라우저를 넘겨줄 때까지 기다리는 시간(기본값: 25, 최대 45, 0 = 즉시 사용 중 보고). 여러 MCP 클라이언트가 동시에 실행 중일 때만 관련됩니다.

  • --browser-min-hold SECONDS - 이 프로세스가 넘겨주기 전에 공유 브라우저를 보유하는 최소 시간(기본값: 20). --browser-wait보다 3초 아래로 제한되므로 함께 높이세요. 값이 높을수록 브라우저 재시작이 줄어들지만 다른 클라이언트의 대기 시간은 길어집니다.

  • --browser-idle-timeout SECONDS - 도구 호출 없이 이 시간이 지나면 유휴 브라우저를 닫고 프로필을 해제합니다(기본값: 600, 0 = 계속 열어 둠)

  • --auto-import / --no-auto-import - 수동 로그인으로 폴백하기 전에 첫 번째 도구 호출에서 로그인된 로컬 브라우저의 세션을 가져옵니다(Docker에서 무시됨). macOS에서는 키체인이 한 번 프롬프트를 표시할 수 있습니다.

  • --user-data-dir PATH - 브라우저 프로필 디렉터리(기본값: ~/.linkedin-mcp/profile). 세션을 회전하거나 지우면 이 디렉터리 와 그 부모(저장된 쿠키와 파생 프로필을 보유한)가 삭제됩니다.

  • --claim-profile-root - 서버가 스스로 소유하지 않을 프로필 디렉터리를 인수합니다(예: 부모에 이미 다른 파일이 있는 경우). 디렉터리당 한 번 필요합니다.

  • --chrome-path PATH - Chrome/Chromium 실행 파일 경로(Docker에서는 거의 필요 없음)

  • --proxy-server URL - scheme://host:port 형식으로 브라우저 트래픽을 프록시로 라우팅합니다. 암호는 PROXY_PASSWORD로 설정하여 프로세스 목록에서 숨깁니다.

[!NOTE] Docker에서 일반 --login에는 여전히 표시되는 창이 없습니다. 일회성 로그인 명령에만 --login-viewer를 추가하고 127.0.0.1:6080:6080을 게시하세요. Docker는 기본적으로 이미 헤드형이므로 --no-headless는 아무것도 변경하지 않습니다. 실험적 --daemon은 소유자가 가상 디스플레이보다 오래 살 수 있으므로 Docker에서 무시됩니다.

HTTP 모드 예시(웹 기반 MCP 클라이언트용):

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

그 두 부분은 모두 필요하며, 각기 다른 역할을 합니다. --host 0.0.0.0은 서버가 컨테이너 내부에서 접근 가능하게 만듭니다. 컨테이너 안에서 127.0.0.1에 바인딩된 프로세스는 게시된 포트를 통해서는 전혀 도달할 수 없습니다. -p 앞의 127.0.0.1:은 외부에서 이 머신으로만 제한하는 역할을 합니다. 이 접두사를 빼면 Docker가 모든 인터페이스에 게시하므로 인증이 없는 엔드포인트가 네트워크에 노출됩니다. 서버는 이 둘을 구분할 수 없으므로 어느 쪽이든 경고합니다.

루프백 게시는 이를 컨테이너가 아니라 머신으로 제한합니다. 같은 호스트의 다른 컨테이너는 host.docker.internal이 resolve되는 곳이라면 어디서든 이를 통해 여전히 접근할 수 있습니다. 이는 Docker Desktop과 OrbStack에서는 기본값이지만 네이티브 Linux Docker에서는 그렇지 않습니다.

런타임 서버 로그는 FastMCP/Uvicorn이 출력합니다.

HTTP 서버는 localhost 또는 자신이 바인딩된 주소로 전달된 요청에만 응답하고, 그 외의 요청은 421로 거부합니다. 이것이 단순히 방문한 웹사이트가 도메인을 이 서버로 지정하고 여러분의 브라우저를 통해 LinkedIn 세션을 사용하는 것을 막아줍니다.

네트워크상의 머신 이름과 리버스 프록시 앞의 공개 이름을 포함해 다른 이름으로 서버에 접근하는 것은 거부됩니다. 프록시가 업스트림 Host를 백엔드 주소로 재작성하게 하거나, 서버를 제공할 호스트 이름을 지정하세요:

FASTMCP_HTTP_ALLOWED_HOSTS='["mcp.example"]'

그러면 정확히 그 이름만 허용하고 다른 모든 것은 계속 거부합니다. 엔드포인트에는 여전히 인증이 없으므로, 자신의 머신 너머에서 접근 가능한 모든 것은 인증을 제공하는 무언가 뒤에 있어야 합니다.

mcp inspector로 테스트:

  1. mcp inspector 설치 및 실행 bunx @modelcontextprotocol/inspector

  2. 브라우저에서 inspector를 열려면 미리 채워진 토큰 url을 클릭하세요

  3. Transport Type으로 Streamable HTTP를 선택하세요

  4. URL을 http://localhost:8080/mcp로 설정하세요

  5. 연결

  6. 도구 테스트

Docker 문제:

  • Docker가 설치되어 있는지 확인하세요

  • Docker가 실행 중인지 확인: docker ps

  • ~/.linkedin-mcp에 대한 권한 오류: 이전의 rootful Docker 실행이 디렉터리를 root로 생성했을 수 있습니다. sudo chown -R "$(id -u):$(id -g)" ~/.linkedin-mcp로 해결하세요.

로그인 문제:

  • 한 번에 하나의 활성 LinkedIn 세션만 있는지 확인하세요

  • --login의 경우 LinkedIn 모바일 앱에서 로그인 확인을 요구할 수 있습니다

  • LinkedIn은 로그인 중에 캡차 챌린지를 표시할 수 있습니다. uvx mcp-server-linkedin@latest --login을 실행하면 캡차를 수동으로 해결할 수 있는 브라우저가 열립니다. 사전 요구 사항은 uvx 설정을 참조하세요.

  • 호스트에서 다시 로그인한 후 Docker 인증이 오래되면, 새 소스 세션 생성에서 fresh-bridge할 수 있도록 Docker를 한 번 다시 시작하세요.

시간 초과 문제:

  • 페이지 작업 실패 (요소를 찾을 수 없음, 탐색 멈춤): 브라우저 페이지 작업 시간 초과를 늘리세요 — --timeout 10000 또는 TIMEOUT=10000 (밀리초, 기본값 5000).

  • 전체 도구 호출 시간 초과 (예: 다중 섹션 프로필, 콜드 스타트 Chromium, 느린 컨테이너): 도구별 실행 시간 초과를 늘리세요 — --tool-timeout 300 또는 TOOL_TIMEOUT=300 (초, 기본값 180).

  • 세션이 없는 첫 번째 도구 호출: 로컬에 로그인된 브라우저에 활성 LinkedIn 세션이 있으면, 수동 로그인을 강제하는 대신 서버가 자동으로 가져옵니다 (AUTO_IMPORT_FROM_BROWSER / --auto-import 참조). macOS에서는 키체인이 Safe Storage 접근 권한을 한 번 요청할 수 있습니다. 가져올 수 있는 브라우저 세션이 없으면 로그인 창 열기로 대체되고 LOGIN_INLINE_WAIT초(기본값 25, 최대 45; --login-inline-wait)까지 대기하므로 빠른 로그인으로 한 번의 호출에 해결됩니다. 대기 시간이 지나면 도구가 대기 신호를 반환하고 모델이 약 30초 후에 재시도합니다. 자동 가져오기와 인라인 대기는 모두 Docker에서 또는 서버가 루프백이 아닌 HTTP 호스트에 바인딩된 경우에는 적용되지 않습니다. --login으로 호스트에서 세션을 만들거나, 명시적인 Docker --login --login-viewer 명령을 사용하세요.

  • 느린 연결을 사용하는 사용자는 어느 쪽이든 더 높은 값이 필요할 수 있습니다.

이미 실행했는데 호스트에서 --login을 실행하라는 안내를 받은 경우:

  • 컨테이너가 아닌 머신에서 도구 호출이 "No valid LinkedIn session is available in Docker"라고 응답하면 런타임이 잘못 감지된 것입니다. 이는 관련 없는 서비스용 Docker 데몬을 실행하는 Linux 호스트에서 발생했습니다. LINKEDIN_MCP_CONTAINER=false로 감지를 재정의하세요. true는 반대를 강제합니다.

프록시 사용:

대부분의 사용자는 프록시를 사용하지 않아야 합니다. LinkedIn이 보안 챌린지를 줄이기 위해 제시하는 자체 지침은 VPN이나 프록시를 피하는 것이며, 세션이 로그인하는 주소를 평가합니다. 수년간 사용해 온 홈 연결은 신뢰 신호입니다. 이력을 알 수 없는 상업용 출구 노드는 그렇지 않으며, 프록시로 전환하는 것 자체가 체크포인트를 유발하는 종류의 변경입니다. 프록시가 가치 있는 경우는 한 가지입니다. 서버가 주소가 명백히 데이터 센터로 보이는 곳이나, 계정 사용 이력과 다른 국가에서 실행되는 경우입니다. 그 경우에도 자체 홈 네트워크의 WireGuard 또는 Tailscale 출구 노드가 유료 제공업체보다 낫습니다. 주소가 실제로 여러분의 것이기 때문입니다. 그래도 구매한다면 회전형 리지덴셜 풀 대신 전용 고정 ISP 주소를 구입해 유지하세요.

  • --proxy-server http://host:port로 브라우저를 프록시에 경유시킵니다 (http, https, socks4, socks5 허용). MCP 전송이 아닌 브라우저 트래픽만 라우팅됩니다.

  • 자격 증명은 PROXY_USERNAME과 PROXY_PASSWORD에 입력합니다. 의도적으로 --proxy-password 플래그는 없습니다. 명령줄 인수는 머신의 다른 모든 사용자가 읽을 수 있기 때문입니다. PROXY_SERVER는 대부분의 제공업체가 제공하는 결합된 http://user:pass@host:port 형식도 허용합니다.

  • Chromium은 SOCKS 프록시에 인증할 수 없으므로 자격 증명에는 http(s) 엔드포인트가 필요합니다. 제공업체가 인증된 SOCKS5만 제공한다면 자격 증명을 보유한 로컬 릴레이를 실행하고 서버를 그쪽으로 지정하세요.

  • 로컬 주소도 프록시를 통해 전달됩니다. 프록시가 설정되면 Chromium의 일반적인 localhost 직접 경로가 제거되므로, 로컬 대상을 직접 연결해야 한다면 PROXY_BYPASS=localhost,127.0.0.1,::1을 추가하세요.

  • 프록시가 구성된 동안 자동 가져오기는 건너뜁니다. 로컬 브라우저에서 가져온 세션은 실제 주소에서 생성된 것이며, 이를 프록시로 옮기는 것이 바로 체크포인트를 유발하는 변경이기 때문입니다. --login을 사용하세요.

  • 잘못된 프록시 비밀번호는 스스로 보고되지 않습니다. Chromium이 페이지 시간 초과까지 인증 챌린지를 재시도하므로 시간 초과 또는 로그인 실패로 표면화됩니다. 프록시를 추가한 직후 세션이 작동을 멈추면 세션이 만료되었다고 가정하기 전에 자격 증명을 확인하세요.

  • 세션을 만들기 전에 프록시를 설정하세요. 프록시가 이미 구성된 상태에서 --login을 실행하세요. 기존 프로필에 프록시를 켜면 로그인된 세션이 새 IP로 이동하며, 이것이 LinkedIn 체크포인트를 유발합니다. 실제 IP에서 생성된 세션을 가져오는 --import-from-browser에도 동일하게 적용됩니다. 같은 이유로 회전형 풀이 아닌 고정 세션을 사용하세요.

사용자 지정 Chrome 경로:

  • Chrome이 표준 위치가 아닌 곳에 설치된 경우 --chrome-path /path/to/chrome을 사용하세요

  • 환경 변수로도 설정할 수 있습니다: CHROME_PATH=/path/to/chrome

  • macOS와 Linux에서 브라우저는 마지막으로 프로필을 연 브라우저보다 최소한 같거나 새로운 버전이어야 하며, 그렇지 않으면 서버가 실행을 거부합니다. (Windows에서는 해당 없음: Windows의 브라우저는 실행하지 않고 버전을 물어볼 수 없으므로 검사가 꺼져 있습니다.) 이전 브라우저는 최신 브라우저가 기록한 저장소를 조용히 삭제할 수 있으며, 그중에는 저장된 세션도 있습니다. 그러면 실패가 만료된 로그인과 똑같이 보입니다. 메시지는 두 버전을 모두 명시합니다. 최신 Chrome을 한 번 실행한 후 번들 Chromium으로 돌아가는 것이 이 조건을 충족하는 일반적인 방법입니다. 그 브라우저가 무엇이든 간에 최신 브라우저를 다시 실행하거나, --login을 실행하세요. --login은 저장된 세션을 옆으로 옮기고 현재 브라우저로 새로 로그인합니다. --logout도 지우지만 옛 세션을 복구 가능하게 유지하는 대신 버리며, 터미널에서 확인을 요구하므로 MCP 클라이언트가 시작한 서버에서는 사용할 수 없습니다.

  • Chrome, Chromium, Chrome for Testing만 이 방식으로 비교됩니다. 포크는 버전 번호를 다르게 매기므로 (Vivaldi는 7.x, Edge의 빌드 번호는 같은 메이저 아래에서 Chrome보다 훨씬 낮음) CHROME_PATH를 포크 중 하나로 지정하면 아무것도 충족할 수 없는 거부가 아니라 검사를 끄게 됩니다.

  • 문서화된 Docker 설정에서는 이 검사가 적용되지 않습니다. 컨테이너는 --login으로 만든 프로필을 절대 열지 않습니다. 쿠키에서 자체 프로필을 파생하며, 기본적으로 시작할 때마다 처음부터 다시 빌드하므로 이전 이미지가 다운그레이드할 것이 없습니다. EXPERIMENTAL_PERSIST_DERIVED_RUNTIME이 설정되면 파생 프로필이 유지되며, 뒤로 이동하는 이미지 태그는 그런 다음 그것을 버리고 다시 파생하므로 역시 여러분이 할 일이 없습니다. 이 검사는 서버가 해당 프로필을 직접 여는 호스트에서 중요합니다. --login 자체 중에는 그렇지 않습니다. --login은 브라우저를 시작하기 전에 이전 프로필을 옆으로 옮기므로 결코 검사에 걸리지 않습니다.

🐍 로컬 설정 (개발 및 기여)

기여를 환영합니다! 아키텍처 지침과 체크리스트는 CONTRIBUTING.md를 참조하세요. PR을 제출하기 전에 기능이나 버그 수정을 논의하려면 먼저 이슈를 열어 주세요.

사전 요구 사항: Git과 uv 설치

설치

# 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

로컬 서버는 MCPB 및 uvx와 동일한 관리형 런타임 흐름을 사용합니다. 백그라운드에서 Patchright Chromium 브라우저 캐시를 준비하고, 인증이 필요한 첫 번째 도구 호출에서 LinkedIn 로그인을 엽니다. 세션을 명시적으로 만들고 싶다면 uv run -m linkedin_mcp_server --login을 실행할 수도 있습니다.

로컬 설정 도움말

CLI 옵션:

  • --login - 브라우저를 열어 로그인하고 세션 저장

  • --import-from-browser [BROWSER] - 로컬에 로그인된 Chromium 브라우저(chrome, chromium, brave, edge, arc, vivaldi, helium, yandex, whale, auto)의 세션을 재사용합니다. 플래그만 사용하면 활성 LinkedIn 세션이 있는 가장 최근 사용 브라우저인 auto를 선택합니다.

  • --status - 저장된 세션이 유효한지 확인한 후 종료

  • --logout - 저장된 세션 지우기

  • --no-headless - 브라우저 창 표시 (디버깅에 유용)

  • --log-level {DEBUG,INFO,WARNING,ERROR} - 로깅 수준 (기본값: WARNING)

  • --transport {stdio,streamable-http} - 전송 모드 강제 (기본값: stdio)

  • --host HOST / --port PORT / --path PATH - HTTP 서버 주소 (기본값: 127.0.0.1, 8000, /mcp)

  • --timeout MS - 단일 페이지 작업 시간 초과 (기본값: 5000)

  • --tool-timeout SECONDS - 전체 도구 호출 시간 초과 (기본값: 180). 대규모 스크래핑, 느린 네트워크 또는 콜드 스타트 브라우저에서는 값을 높이세요.

  • --user-data-dir PATH - 브라우저 프로필 디렉터리 (기본값: ~/.linkedin-mcp/profile). 세션을 회전시키거나 지우면 이 디렉터리 와 상위 디렉터리가 삭제되며, 상위 디렉터리에는 저장된 쿠키와 파생 프로필이 들어 있습니다.

  • --claim-profile-root - 서버가 자체적으로 소유하지 않을 프로필 디렉터리를 인수합니다. 예를 들어 상위 디렉터리에 다른 파일이 이미 있는 경우입니다. 디렉터리당 한 번 필요합니다.

  • --slow-mo MS - 브라우저 작업 사이의 지연 (기본값: 0, 디버깅에 유용)

  • --viewport WxH - 뷰포트 크기 (기본값: 1280x720). 창 없는 모드에만 적용됩니다. 창이 있는 실행은 실제 창 크기를 사용합니다.

  • --chrome-path PATH - Chrome/Chromium 실행 파일 경로

  • --proxy-server URL - scheme://host:port 형식으로 브라우저 트래픽을 프록시에 경유시킵니다. 비밀번호는 PROXY_PASSWORD로 설정하며, 이렇게 하면 프로세스 목록에 노출되지 않습니다.

  • --help - 도움말 표시

참고: 대부분의 CLI 옵션에는 동일한 환경 변수가 있습니다. 자세한 내용은 .env.example을 참조하세요.

HTTP 모드 예시 (웹 기반 MCP 클라이언트용):

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가 사용됩니다.

로그인 문제:

  • 한 번에 하나의 활성 LinkedIn 세션만 유지하세요

  • LinkedIn은 --login 시 LinkedIn 모바일 앱에서 로그인 확인을 요구할 수 있습니다

  • LinkedIn은 로그인 중 캡차(captcha) 챌린지를 표시할 수 있습니다. --login 명령은 브라우저를 열어 수동으로 해결할 수 있게 합니다.

스크래핑 문제:

  • --no-headless를 사용하여 브라우저 동작을 확인하고 스크래핑 문제를 디버깅하세요

  • --log-level DEBUG를 추가하여 더 상세한 로깅을 확인하세요

세션 문제:

  • 브라우저 프로필은 ~/.linkedin-mcp/profile/에 저장됩니다

  • 관리형 브라우저 다운로드는 ~/.linkedin-mcp/patchright-browsers/에 캐시되며, uvx 및 MCP Bundle 설치와 공유됩니다

  • 브라우저 캐시는 계속 커집니다: Patchright는 설치된 버전이 여전히 참조하는 한 이전 Chromium 버전을 유지하며, uv 아카이브나 두 번째 작업 트리(worktree)가 그러한 참조입니다. 서버는 보유 중인 항목을 명명하는 경고를 기록합니다. 공간을 확보하려면 모든 LinkedIn MCP Server 인스턴스를 중지하고 ~/.linkedin-mcp/patchright-browsers/를 삭제한 후, 다음 실행 시 현재 브라우저를 다운로드하도록 하세요.

  • --logout을 사용하여 프로필을 지우고 새로 시작하세요

Python/Patchright 문제:

  • Python 버전 확인: python --version (3.12+여야 함)

  • Patchright 재설치: uv run patchright install chromium

  • 의존성 재설치: uv sync --reinstall

시간 초과 문제:

  • 페이지 작업 실패 (요소를 찾지 못함, 탐색 중단): 브라우저 페이지 작업 시간 초과를 늘리세요 — --timeout 10000 또는 TIMEOUT=10000 (밀리초, 기본값 5000).

  • 전체 도구 호출 시간 초과 (예: 다중 섹션 프로필, 콜드 스타트 Chromium, 느린 컨테이너): 도구별 실행 시간 초과를 늘리세요 — --tool-timeout 300 또는 TOOL_TIMEOUT=300 (초, 기본값 180).

  • 세션이 없는 첫 도구 호출: 로컬에 로그인된 브라우저에 활성 LinkedIn 세션이 있으면, 서버는 수동 로그인을 강제하는 대신 이를 자동으로 가져옵니다 (AUTO_IMPORT_FROM_BROWSER / --auto-import 참조). macOS에서는 키체인이 Safe Storage 접근에 대해 한 번 프롬프트를 표시할 수 있습니다. 가져올 수 있는 브라우저 세션이 없으면 로그인 창을 열고 LOGIN_INLINE_WAIT초(기본값 25, 최대 45; --login-inline-wait) 동안 대기하여 빠른 로그인이 한 번의 호출로 해결되도록 합니다. 대기 시간이 경과하면 도구는 보류 신호를 반환하고 모델은 약 30초 후에 재시도합니다. 자동 가져오기와 인라인 대기 모두 Docker 환경이나 서버가 루프백이 아닌 HTTP 호스트에 바인딩된 경우에는 적용되지 않습니다. 호스트에서 --login으로 세션을 생성하거나, 명시적인 Docker --login --login-viewer 명령을 사용하세요.

  • 느린 연결을 사용하는 사용자는 두 값 모두 더 높게 설정해야 할 수 있습니다.

이미 --login을 실행했는데 호스트에서 실행하라는 안내를 받은 경우:

  • 컨테이너가 아닌 머신에서 도구 호출이 "Docker에서 유효한 LinkedIn 세션을 사용할 수 없습니다"라고 응답하면 런타임이 잘못 감지된 것입니다. 이는 관련 없는 서비스용 Docker 데몬을 실행하는 Linux 호스트에서 발생했습니다. LINKEDIN_MCP_CONTAINER=false를 설정하여 감지를 재정의하세요. true는 반대를 강제합니다.

프록시 사용:

대부분의 사용자는 프록시를 사용하지 않아야 합니다. LinkedIn이 보안 챌린지를 줄이기 위한 자체 지침은 VPN이나 프록시를 피하는 것이며, 세션이 로그인하는 주소를 평가합니다. 수년간 사용해 온 홈 연결은 신뢰 신호입니다. 이력을 알 수 없는 상용 출구 노드는 그렇지 않으며, 프록시로 전환하는 것 자체가 체크포인트를 유발하는 종류의 변경입니다. 프록시가 가치 있는 경우는 한 가지입니다: 서버가 주소가 명백히 데이터 센터로 보이는 곳이나 계정 이력과 다른 국가에서 실행되는 경우입니다. 그 경우에도, 자체 홈 네트워크의 WireGuard 또는 Tailscale 출구 노드가 유료 제공업체보다 낫습니다. 주소가 실제로 당신의 것이기 때문입니다. 구매한다면 회전형 리지덴셜 풀 대신 전용 고정 ISP 주소를 사용하고 유지하세요.

  • --proxy-server http://host:port로 브라우저를 프록시를 통해 라우팅하세요 (http, https, socks4, socks5 허용). 브라우저 트래픽만 라우팅되며 MCP 전송은 라우팅되지 않습니다.

  • 자격 증명은 PROXY_USERNAME 및 PROXY_PASSWORD에 넣습니다. 의도적으로 --proxy-password 플래그는 없습니다: 명령줄 인수는 머신의 다른 모든 사용자가 읽을 수 있기 때문입니다. PROXY_SERVER는 대부분의 제공업체가 제공하는 결합된 http://user:pass@host:port 형식도 허용합니다.

  • Chromium은 SOCKS 프록시에 인증할 수 없으므로 자격 증명에는 http(s) 엔드포인트가 필요합니다. 제공업체가 인증된 SOCKS5만 제공하는 경우, 자격 증명을 보유한 로컬 릴레이를 실행하고 서버를 해당 릴레이로 지정하세요.

  • 로컬 주소도 프록시를 통해 전달됩니다. 프록시가 설정되면 Chromium의 일반적인 localhost 직접 경로가 제거되므로, 로컬 대상을 직접 연결해야 하는 경우 PROXY_BYPASS=localhost,127.0.0.1,::1을 추가하세요.

  • 프록시가 구성된 동안 자동 가져오기는 건너뜁니다: 로컬 브라우저에서 가져온 세션은 실제 주소에서 생성된 것이며, 이를 프록시로 이동하는 것은 체크포인트를 유발하는 바로 그 변경입니다. --login을 사용하세요.

  • 잘못된 프록시 비밀번호는 스스로 보고되지 않습니다: Chromium은 페이지가 시간 초과될 때까지 인증 챌린지를 재시도하므로 시간 초과 또는 로그인 실패로 표시됩니다. 프록시를 추가한 직후 세션이 작동을 멈추면 세션이 만료되었다고 가정하기 전에 자격 증명을 확인하세요.

  • 세션을 만들기 전에 프록시를 설정하세요. 프록시가 이미 구성된 상태에서 --login을 실행하세요. 기존 프로필에 프록시를 켜면 로그인된 세션이 새 IP로 이동하며, 이것이 LinkedIn 체크포인트를 유발하는 것입니다. --import-from-browser에도 동일하게 적용되며, 이는 실제 IP에서 생성된 세션을 가져옵니다. 같은 이유로 회전형 풀이 아닌 고정 세션(sticky session)을 사용하세요.

사용자 지정 Chrome 경로:

  • Chrome이 비표준 위치에 설치된 경우 --chrome-path /path/to/chrome을 사용하세요

  • 환경 변수로도 설정 가능: CHROME_PATH=/path/to/chrome

  • macOS 및 Linux에서 브라우저는 프로필을 마지막으로 연 브라우저보다 최소한 같거나 새로운 버전이어야 하며, 그렇지 않으면 서버가 실행을 거부합니다. (Windows는 아님: Windows의 브라우저는 시작하지 않고는 버전을 물어볼 수 없으므로 검사가 꺼져 있습니다.) 이전 브라우저는 최신 브라우저가 기록한 저장소(저장된 세션 포함)를 조용히 버릴 수 있으며, 실패는 만료된 로그인과 정확히 동일하게 보입니다. 메시지는 두 버전을 모두 명명합니다. 최신 Chrome을 한 번 실행한 후 번들 Chromium으로 돌아가는 것이 이 문제를 해결하는 일반적인 방법입니다. 실행했던 최신 브라우저를 다시 실행하거나, --login을 실행하여 저장된 세션을 옆으로 옮기고 현재 브라우저로 새로 로그인하세요. --logout도 이를 지우지만 복구 가능하게 유지하는 대신 이전 세션을 폐기하며, 터미널에서 확인을 요구하므로 MCP 클라이언트가 시작한 서버에서는 사용할 수 없습니다.

  • Chrome, Chromium 및 Chrome for Testing만 이 방식으로 비교됩니다. 포크(fork)는 버전 번호가 다르게 매겨지므로(Vivaldi는 7.x, Edge의 빌드 번호는 동일한 메이저 아래에서 Chrome보다 훨씬 낮음), CHROME_PATH를 포크에 지정하면 거부가 아닌 검사가 꺼집니다.

[!IMPORTANT] FAQ

사용해도 안전한가요? 계정이 차단될 수 있나요? 이 도구는 실제 브라우저 세션을 제어합니다. 문서화되지 않은 API를 악용하거나 인증을 우회하지 않습니다. LinkedIn의 사용자 계약은 자동화된 접근을 금지하며, 자동화 도구를 사용하는 계정은 제한되거나 차단될 수 있습니다. 사용에 따른 책임은 본인에게 있으며 계정 안전을 보장하지 않습니다. 문제가 발생하면 Discussions에서 알려주세요.

내 에이전트가 너무 많은 작업을 실행하면 어떻게 되나요? 도구 호출은 큐를 통해 순차적으로 실행됩니다. 실행하는 자동화의 양에 대한 책임은 사용자에게 있습니다. 절제해서 사용하고 에이전트에 책임감 있게 프롬프트하세요.

감사의 말

FastMCP 및 Patchright로 구축되었습니다.

LinkedIn 사용자 계약에 따라 사용하세요. 자동화된 접근은 LinkedIn의 약관을 위반할 수 있으며 계정 제한으로 이어질 수 있습니다. 이 도구는 개인 사용 전용이며 어떠한 종류의 보증도 제공하지 않습니다.

라이선스

이 프로젝트는 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 recent community 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.
    35
    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