Skip to main content
Glama
TSS99
by TSS99

LinkedIn MCP

AI 어시스턴트가 DevTools 프로토콜을 통해 실제 Chrome 창을 구동하여 LinkedIn 채용 정보를 검색하고 LinkedIn 프로필을 읽을 수 있게 해 주는 MCP 서버입니다.

이 서버는 읽기 전용입니다. 연결, 메시지, 추천, 게시, 지원을 수행하는 도구는 여기에 없습니다. 설정에서 비활성화된 것이 아니라, 그런 코드 자체가 존재하지 않기 때문입니다. 이것은 의도적인 경계선입니다. LinkedIn은 자동화된 쓰기를 자동화된 읽기보다 훨씬 엄격하게 다루며, 이 둘을 섞는 것이 계정이 제한되는 원인이 됩니다.

도구

도구

반환 내용

linkedin_search_jobs

제목, 회사, 위치, 근무 형태, 게시 당시 연봉, 게시 후 경과 시간, job_id를 포함한 채용 목록. 필터: 위치, 게시 후 기간, 경력 수준, 고용 형태, 근무 형태, Easy Apply, 정렬 순서.

linkedin_get_job

채용 공고 하나를 전체 공개 — 회사, 위치, LinkedIn의 채용 인사이트, 그리고 '더 보기' 접힘이 펼쳐진 전체 설명.

linkedin_get_profile

이름, 헤드라인, 위치, 소개(About) 텍스트, 경력 사항, 학력 및 기술.

linkedin_check_session

저장된 브라우저 세션이 여전히 로그인 상태인지 여부.

linkedin_close_session

Chrome에서 분리하여 창과 세션을 그대도 둡니다.

Related MCP server: LinkedIn MCP Server

설치

Python 3.12+, uv, Google Chrome이 필요합니다.

git clone https://github.com/TSS99/linkedin-mcp.git
cd linkedin-mcp
uv sync

한 번 로그인하세요. 그러면 Chrome 창이 열리고 직접 로그인할 때까지 기다립니다. 스크립트가 자격 증명을 입령하는 일은 절대 없습니다. LinkedIn이 스크립트 기반 자격 증명 입령을 차단하기 때문입니다.

uv run linkedin-mcp --login

세션은 ~/.linkedin-mcp/chrome-profile에 유지됩니다. 언제든지 uv run linkedin-mcp --check로 확인하고, uv run linkedin-mcp --logout으로 삭제할 수 있습니다.

어떤 Chrome 프로필을 구동하는가

기본적으로 서버는 자체 임시 프로필을 엽니다. 그 창은 완전히 새것처럼 보입니다 — 즸겨찾기 없음, 확장 프로그램 없음, LinkedIn 외에는 로그인된 것이 없음. 이것이 핵심입니다. 서버는 오직 LinkedIn만 볼 수 있습니다.

만약 평소 사용하는 Chrome을 구동하게 하려면 — 이미 로그인된 LinkedIn 세션을 재사용하고 낯선 창을 열지 않도록 — 다음을 설정하세요:

LINKEDIN_MCP_PROFILE_DIR=system

또는 원하는 프로필 디렉터리를 명시적으로 지정하세요. MCP 클라이언트 구정에서는 env 블록에 넣습니다:

{
  "mcpServers": {
    "linkedin": {
      "command": "uv",
      "args": ["--directory", "/path/to/linkedin-mcp", "run", "linkedin-mcp"],
      "env": { "LINKEDIN_MCP_PROFILE_DIR": "system" }
    }
  }
}

이렇게 하기 전에 이해해야 할 두 가지가 있습니다:

Chrome을 한 번은 재시작해야 합니다. --remote-debugging-port는 시잭 시에만 적요됩니다. 이미 실해 중인 프로세스에서는 킬 수 없습니다. 따라서 지금 열려 있는 Chrome은 프로필 설정과 관계없이 절대 연결할 수 없습니다. Chrome을 완전히 종료하고(Cmd+Q, 창을 닫는 것만으로는 부족) 서버가 시작하게 하거나, --login이 출력하는 명령으로 직접 시작하세요.

디버그 포트는 LinkedIn에 한정되지 않습니다. 127.0.0.1:9224에 접근할 수 있는 무엇이든 그 Chrome의 모든 탭을 조작하고 그 안의 모든 세션을 읽을 수 있습니다 — LinkedIn뿐만 아니라 메일, 은행, 전부 다요. 격리된 프로필에는 그 외에 접근할 것이 없습니다. 하지만 평소 프로필에는 모든 것이 있습니다. 신뢰하는 컴퓨터에서만 이런 방식으로 실행하고, 작업이 끝나면 디버그 Chrome을 닫으세요.

--logout은 자신이 생성하지 않은 프로필은 삭제하지 않습니다. 따라서 이 서버를 실제 Chrome에 지정해도 브라우저 상태가 지워지지 않습니다.

설정

MCP 클라이언트 구성에 추가하세요 (mcp-config.example.json 참조):

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

Claude Code의 경우: claude mcp add linkedin -- uv --directory /path/to/linkedin-mcp run linkedin-mcp

작동 방식과 이유

별도로 실행된 브라우저가 아닌 실제 Chrome 프로필에 CDP로 연결합니다. Playwright 자체의 Chromium은 LinkedIn이 검사하는 여러 방식으로 자신을 드러냅니다. 직접 로그인한 실제 Chrome에 연결하면 브라우저 지문과 쿠키가 그대로 유지됩니다. 서버는 디버그 포트 9224에서 실행되므로 9222/9223 포트의 다른 브라우저 기반 MCP 서버와 공존할 수 있습니다.

탐색은 속도가 조절됩니다. LinkedIn은 요청량뿐 아니라 호출 주기로도 요청을 제한합니다. 따라서 goto는 지터(jitter)가 적용된 최소 간격을 강제합니다. 오랜 연구 작업이 가능한 것보다 느린 것은 의도된 것입니다.

LinkedIn의 DOM에 있는 모든 문자열은 두 번 나타납니다 — 한 번은 시각적으로, 한 번은 스크린 리더를 위한 visually-hidden span으로. 따라서 원시 innerText는 "Acme Corp\nAcme Corp"로 읽힙니다. dedupe_lines는 연속된 중복을 제거합니다. 이 기능이 없으면 파싱된 모든 필드가 두 배로 나옵니다.

선택자는 순서가 있는 폴백 목록입니다. LinkedIn의 클래스 이름은 난독화되어 있고 자주 바뀝니다. 가능한 경우 파서는 클래스 변동을 견뎌낸 요소 — data-occludable-job-id 속성, 안정적인 div#experience 앵커 ID —에 기반을 두고, 필드별 훅을 신뢰하기보다 카드 텍스트에서 줄 순서를 파싱하는 방식으로 폴백합니다.

실패한 스크래핑은 절대 빈 결과를 반환하지 않습니다. 모든 도구는 래퍼로 감싸져 있어, 앵커가 없으면 선택자와 URL을 명시하는 {"status": "error", "error_type": "stale_selector", ...}을 반환합니다. []를 받은 LLM은 "채용 정보를 찾을 수 없음"이라고 확신하며 보고할 것입니다. 이렇게 하면 도구 오작동과 실제로 결과가 없는 경우를 구분할 수 있습니다.

테스트

uv run pytest

테스트는 순수 파서 — URL/필터 구성, 카드 파싱, 프로필 항목 파싱, 줄 중복 제거 —를 LinkedIn DOM이 실제로 생성하는 형태의 픽스처와 대조하여 검증합니다. 브라우저와 네트워크가 필요 없습니다.

문제가 발생하는 경우

반드시 그렇습니다. LinkedIn은 마크업 변경을 지속적으로 배포하며, 스크레이퍼는 남의 HTML에 대한 추측일 뿐입니다. 언젠가는 stale_selector 오류가 발생할 것이라고 예상하세요. 해결책은 보통 tools/jobs.py나 tools/profiles.py의 선택자 목록에 항목을 하나 더 추가하고, tests/test_parsers.py에 픽스처를 하나 추가하는 것입니다.

auth_required와 함께 checkpoint URL이 나오면, LinkedIn이 사람을 요구하는 것입니다. Chrome 창을 열고 챌린지를 해결한 다음 다시 시도하세요.

이용 약관에 대하여

구현이 아무리 신중해도 자동 접근은 LinkedIn 사용자 약관에 위배됩니다. LinkedIn은 이러한 이유로 계정을 제한하기도 합니다. 이 도구는 개인 연구 용도입니다. 읽기 전용 설계와 속도 조절 요청이 위험을 줄여 주지만 없애지는 않으며, 그 위험은 이 도구에 연결한 계정이 부담합니다. 판단하시기 바랍니다.

라이선스

Apache-2.0

Available Tools

5 tools
linkedin_check_sessionA

Check whether the browser is signed in to LinkedIn.

Every other tool needs this to be true; LinkedIn serves a login wall to anonymous visitors on job listings and profiles alike.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior3/5

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

With no annotations, the description must carry the behavioral burden. It states the check itself but does not explicitly confirm it is non-mutating or describe the return format. The login-wall context implies safety, but the description lacks explicit boundary details. It does not contradict anything, but could be more transparent about side effects.

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, no filler. The purpose is stated first, and the second sentence adds valuable context about why this tool matters. 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 parameterless check with no output schema, the description fully covers what an agent needs: what the tool does and why it's important before other tools. It is complete and self-sufficient.

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 already complete (100% coverage). Baseline is 4. The description adds no parameter information, which is appropriate since there are none to document.

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?

Clearly states a specific verb ('check') and resource ('whether the browser is signed in to LinkedIn'). The description distinguishes it from sibling tools by its unique purpose—session verification—and adds context about the login wall, making it unambiguous what this tool does.

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?

Explicitly states that 'every other tool needs this to be true,' implying it should be called before other LinkedIn operations. This provides clear usage context. It does not list exclusions or alternatives, but given its singular nature, the guidance is sufficient.

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

linkedin_close_sessionA

Disconnect from the browser and free resources.

This detaches from Chrome; it leaves the window and the saved session alone.

NameRequiredDescriptionDefault

No parameters

TDQS

A4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden. It transparently discloses the key side effect: it does NOT close the window or the saved session, and it indicates resource freeing. This goes beyond a simple 'close session' and prevents the agent from assuming destructive behavior.

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 zero waste. The core action is front-loaded, and the clarifying sentence adds essential side-effect information without redundancy.

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 parameterless tool with no output schema, the description is sufficient. It covers what it does and what it doesn't do. One could add typical usage timing (e.g., 'call at end of session'), but that is minor and not strictly necessary for correct invocation.

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?

There are zero parameters, so schema coverage is trivially 100%. The description adds no parameter meaning because none exist; per rubric, a baseline of 4 is appropriate for a parameterless tool.

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 and resource: 'Disconnect from the browser and free resources.' It further clarifies by specifying it detaches from Chrome and leaves the window and saved session intact, distinguishing it clearly from the search/get/check siblings.

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 explicit when-to-use or when-not-to-use guidance. It does not mention that it should be used after other LinkedIn operations or contrast itself with linkedin_check_session. The implication is present but not stated, leaving the agent to infer usage context.

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

linkedin_get_jobA

Get the full detail for one job posting.

Returns the title, company, location, posted age, LinkedIn's job insights (seniority, employment type, headcount) and the complete job description with the "See more" clamp expanded.

NameRequiredDescriptionDefault
jobYesJob id, or a /jobs/view/<id> LinkedIn URL

TDQS

A4/5.0
Behavior3/5

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

With no annotations, the description must bear the burden. It discloses the output content, including the 'See more' clamp expansion, which is a concrete behavior. However, it does not mention prerequisites like authentication needs, rate limits, or error behavior. For a read operation, this is acceptable but not exhaustive, so a 3 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 description is two efficient sentences. The first states the overall purpose, and the second lists the return fields with the clamp expansion noted. No fluff, front-loaded key info, and 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?

Despite having no output schema, the description lists the return values in detail, providing adequate information for an agent to know what to expect. It does not cover prerequisites like active sessions (sibling check_session exists) or error cases, but for a simple GET with clear return fields, it is nearly complete.

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% for the single parameter, already specifying it accepts a job ID or URL. The description itself does not add additional semantics beyond what the schema provides. Baseline 3 is correct given the schema's completeness.

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 full details for a single job posting and enumerates the exact fields returned (title, company, location, posted age, insights, complete description). This verb+resource focus distinguishes it from siblings like search, profile, and session tools.

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: it requires a job ID or URL to retrieve full details. The context is clear that this is for a single job, not searches or profiles, but it does not explicitly mention when not to use it or name alternatives. Still, for a straightforward GET tool, the usage context is unambiguous.

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

linkedin_get_profileA

Read a LinkedIn profile.

Returns name, headline and location, plus the about text, experience history, education and listed skills unless include_sections is false.

Set include_sections to false when you only need to confirm who someone is; it is one page load either way but a much smaller result.

NameRequiredDescriptionDefault
profileYesProfile slug, e.g. 'satyanadella', or a full /in/<slug> URL
include_sectionsNoInclude about, experience, education and skills

TDQS

A4.2/5.0
Behavior3/5

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

With no annotations, the description carries the full burden. It transparently discloses the return content and the page-load trade-off, but omits any session/auth prerequisite or error behavior. This is partially transparent but not comprehensive.

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?

Three terse sentences, each earning its place: purpose, returns, and the parameter trade-off. The essential information is front-loaded with zero fluff.

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 read-only profile tool with no output schema, the description covers what's returned and the parameter option. It omits explicit session requirements, but sibling tools (check_session/close_session) imply that context, so it's not a critical gap.

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 parameters are documented. The description adds value for include_sections by explaining the decision rule and its result-size impact, and reinforces the profile format. This exceeds the baseline.

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 clear verb-resource pair ('Read a LinkedIn profile') and then lists the specific fields returned (name, headline, location, about, experience, education, skills). This unambiguously distinguishes it from sibling job-search and session tools.

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 purpose is explicit, and the include_sections guidance gives a concrete conditional ('Set include_sections to false when you only need to confirm who someone is') with a performance trade-off. It doesn't explicitly contrast with siblings, but the domain is distinct enough that this is sufficient.

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

linkedin_search_jobsA

Search job listings on LinkedIn.

Returns each listing with title, company, location, workplace type, posted salary where the employer provided one, how long ago it was posted, and the job_id. Pass that job_id to linkedin_get_job for the full description rather than re-searching.

Results are paged 25 at a time, so a large limit means several page loads.

NameRequiredDescriptionDefault
sortNoOrder: 'date' or 'relevance'
limitNoMaximum number of results
job_typeNoOne of: full-time, part-time, contract, temporary, internship, volunteer, other
keywordsYesSearch keywords, e.g. 'machine learning engineer'
locationNoCity, region or country, e.g. 'Bengaluru' or 'India'
easy_applyNoRestrict to Easy Apply listings
workplace_typeNoOne of: on-site, remote, hybrid
experience_levelNoOne of: internship, entry, associate, mid-senior, director, executive
posted_within_daysNoOnly jobs posted within this many days

TDQS

A4.1/5.0
Behavior3/5

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

The description discloses that results are paged 25 at a time and that salary may be absent, but it does not mention authentication/session requirements or rate limits. With no annotations provided, the description carries the full burden, and the existence of linkedin_check_session suggests a session prerequisite that is not mentioned. This is a notable gap.

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 about 100 words, front-loaded with the main purpose, and the second paragraph covers pagination. It avoids redundancy and each sentence contributes value, such as noting the paging limit and the alternative tool. No fluff or repetition.

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?

The description explains the return fields and pagination, and guides to linkedin_get_job, which covers essential operational details. However, it does not mention prerequisites like an active LinkedIn session (implied by check_session sibling) or error/edge-case behavior. Given the parameter count and no output schema, the description is fairly complete but misses these key operational aspects.

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 100% description coverage for all 9 parameters, so the schema already documents their meaning. The description does not add additional parameter semantics beyond what the schema offers (e.g., it does not clarify how sort values map to behavior or the exact format of location). Baseline 3 is appropriate given the schema does the heavy lifting.

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 searches LinkedIn job listings, and explicitly distinguishes itself from the sibling linkedin_get_job by instructing to pass the returned job_id to that tool for full descriptions. This separates purpose from the retrieval sibling without opening the schema.

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 explicitly tells the agent to use linkedin_get_job for the full description rather than re-searching, which is a clear directive about when to use an alternative. It also implicitly distinguishes from profile/session tools by focusing on job search, so usage context is evident.

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. 5 tool updatesv0.1.0
    • First observedlinkedin_check_session
    • First observedlinkedin_close_session
    • First observedlinkedin_get_job
    • First observedlinkedin_get_profile
    • First observedlinkedin_search_jobs

TDQS

A4.3/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: searching jobs, fetching job details, reading profiles, and managing session state. No overlap between the data-access tools and the session-management tools.

Naming Consistency5/5

All five tools follow a consistent 'linkedin_<verb>_<noun>' pattern (search_jobs, get_job, get_profile, check_session, close_session). The naming is uniform and predictable.

Tool Count5/5

Five tools is well within the ideal range for a focused server. Every tool contributes to a clear workflow: session management, job search, job details, and profile lookup.

Completeness4/5

The server covers the core read workflows for LinkedIn jobs and profiles, but lacks profile search or listing capabilities. However, for its stated purpose (searching jobs and reading profiles), the surface is largely complete.

Maintenance

ActivityStale
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables searching and scraping of LinkedIn for structured data on people, companies, and job listings. It allows AI clients to retrieve detailed profiles, experience, and activity sections using browser automation.
    7
    207
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to search, filter, and extract job listings from LinkedIn using an automated headless browser with semantic AI filtering and deduplication.
    11 npm
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Lets an AI assistant operate LinkedIn through an authenticated browser session, enabling profile management, posting, networking, messaging, job search, and automated applications.
    100
    12 npm
    1
    MIT