#
tokens: 3318/50000 8/8 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .gitignore
├── .python-version
├── Dockerfile
├── LICENSE
├── pyproject.toml
├── README.md
├── smithery.yaml
└── src
    └── mcp_linkedin
        ├── __init__.py
        └── client.py
```

# Files

--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------

```
1 | 3.13
2 | 
```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
1 | explore.py
2 | __pycache__
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | # MCP LinkedIn
  2 | 
  3 | A Model Context Protocol (MCP) server that provides tools to interact with LinkedIn's Feeds and Job API.
  4 | 
  5 | This is using unofficial LinkedIn API via [Linkedin-api](https://github.com/tomquirk/linkedin-api). Use at your own risk.
  6 | 
  7 | <a href="https://smithery.ai/server/mcp-linkedin"><img alt="Smithery Badge" src="https://smithery.ai/badge/mcp-linkedin"></a>
  8 | <a href="https://glama.ai/mcp/servers/dvbdubl2bg"><img width="380" height="200" src="https://glama.ai/mcp/servers/dvbdubl2bg/badge" alt="mcp-linkedin MCP server" /></a>
  9 | 
 10 | ### Installing via Smithery
 11 | 
 12 | To install LinkedIn Interaction Server for Claude Desktop automatically via [Smithery](https://smithery.ai/server/mcp-linkedin):
 13 | 
 14 | ```bash
 15 | npx -y @smithery/cli install mcp-linkedin --client claude
 16 | ```
 17 | 
 18 | ## Configuration
 19 | 
 20 | ```json
 21 | {
 22 |     "mcpServers": {
 23 |         "linkedin": {
 24 |             "command": "uvx",
 25 |             "args": ["--from", "git+https://github.com/adhikasp/mcp-linkedin", "mcp-linkedin"],
 26 |             "env": {
 27 |                 "LINKEDIN_EMAIL": "your_linkedin_email",
 28 |                 "LINKEDIN_PASSWORD": "your_linkedin_password"
 29 |             }
 30 |         }
 31 |     }
 32 | }
 33 | ```
 34 | 
 35 | ## Sample usage
 36 | 
 37 | Using [mcp-client-cli](https://github.com/adhikasp/mcp-client-cli)
 38 | 
 39 | ### Get feed posts
 40 | 
 41 | ```
 42 | $ llm whats happening in linkedin feed? Do not mention names
 43 | 
 44 | I'll retrieve the recent LinkedIn feed posts without mentioning any specific names.
 45 | 
 46 | Tool Calls:
 47 |   get_feed_posts
 48 |   Args:
 49 |     limit: 10
 50 | 
 51 | Based on the LinkedIn feed, here are the key highlights without mentioning specific names:
 52 | 
 53 | 1. Data Science & Cybersecurity Insights:
 54 |    - A post about a massive dataset from a major tech company
 55 |    - Includes 13 million pieces of evidence
 56 |    - Covers SIEM telemetry from 6,100 organizations
 57 |    - Represents 441 MITRE ATT&CK techniques
 58 | 
 59 | 2. DevOps Community Event:
 60 |    - A local DevOps meetup was held at a tech company office
 61 |    - Discussed topics like AWS Lambda, Kubernetes scaling, Terraform
 62 |    - Highlighted the importance of networking and continuous learning
 63 |    - Shared experiences of transitioning between tech roles
 64 | 
 65 | 3. Linux Engineering Perspectives:
 66 |    - Insights into what makes a great Linux engineer
 67 |    - Key skills include:
 68 |      * Command-line troubleshooting
 69 |      * Process management
 70 |      * Networking fundamentals
 71 |      * System architecture understanding
 72 |      * Task automation
 73 |      * Shell scripting
 74 | 
 75 | 4. Professional Networking:
 76 |    - Some posts about job seeking
 77 |    - Discussions about career transitions
 78 |    - Sharing professional experiences and learnings
 79 | 
 80 | 5. Tech Community Reflections:
 81 |    - Posts about inspirational figures
 82 |    - Discussions on professional growth
 83 |    - Reflections on learning and personal development
 84 | 
 85 | The feed showcases a mix of technical insights, professional networking, career development, and community engagement across various tech domains.
 86 | ```
 87 | 
 88 | ### Search for jobs
 89 | 
 90 | ```
 91 | $ llm search for 3 data engineer jobs in jakarta. For each job check if it a good match for me by analyzing it against my resume in file resume.md. Do not mention company name in your result but only generic area where the company business is about
 92 | 
 93 | I'll help you find data engineer jobs in Jakarta and analyze them against your resume. I'll break this down into steps:
 94 | 
 95 | 1. First, I'll search for data engineer jobs in Jakarta
 96 | 2. Then, I'll read your resume
 97 | 3. Finally, I'll analyze the job matches
 98 | 
 99 | Let's start by searching for jobs:
100 | 
101 | Tool Calls:
102 |   search_jobs
103 |   Args:
104 |     keywords: data engineer
105 |     location: Jakarta
106 |     limit: 3
107 | 
108 | 
109 | Now, I'll read your resume:
110 | 
111 | Tool Calls:
112 |   read_file
113 |   Args:
114 |     path: resume.md
115 | Secure MCP Filesystem Server running on stdio
116 | Allowed directories: [ '/home/adhikasp', '/mnt/e' ]
117 | 
118 | 
119 | Now, I'll analyze the jobs against your resume:
120 | 
121 | 1. Job in Financial Technology Sector (Lead Backend Engineer):
122 |    - Match Score: 85%
123 |    - Strengths:
124 |      * Requires experience in developing scalable microservices (aligns with your Grab experience)
125 |      * Strong focus on cloud infrastructure (AWS, GCP) - matches your cloud skills
126 |      * Requires experience with event-driven architecture and message brokers
127 |      * Requires Go or Python programming (your proficient languages)
128 |    - Potential Gaps:
129 |      * Specific focus on credit risk and fraud detection might require additional domain knowledge
130 |      * Emphasis on team leadership (6+ years experience leading teams)
131 | 
132 | 2. Job in Financial Technology Sector (DevOps Engineer):
133 |    - Match Score: 75%
134 |    - Strengths:
135 |      * Requires cloud platform experience (AWS, GCP)
136 |      * Needs containerization skills (Docker, Kubernetes)
137 |      * Requires scripting in Python and Bash
138 |      * Needs infrastructure as code experience
139 |    - Potential Gaps:
140 |      * More DevOps focused compared to your backend engineering background
141 |      * Specific monitoring tools might require additional learning
142 | 
143 | 3. Job in Enterprise Collaboration Software (Solution Engineer):
144 |    - Match Score: 60%
145 |    - Strengths:
146 |      * Requires strong communication skills
147 |      * Technical consulting background
148 |      * Experience with enterprise software
149 |    - Potential Gaps:
150 |      * Less technical compared to your current role
151 |      * More sales-oriented solution engineering
152 |      * Less hands-on technical development
153 | 
154 | Recommendation:
155 | The first job (Lead Backend Engineer) appears to be the best match for your skills and experience. It closely aligns with your current work, particularly in terms of backend development, cloud infrastructure, and working with distributed systems. The role's requirements in Go/Python, microservices, and event-driven architecture are very compatible with your professional background.
156 | 
157 | Would you like me to elaborate on any of these job analyses or provide more detailed insights?
158 | ```
159 | 
```

--------------------------------------------------------------------------------
/src/mcp_linkedin/__init__.py:
--------------------------------------------------------------------------------

```python
1 | 
```

--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------

```toml
 1 | [build-system]
 2 | requires = ["hatchling"]
 3 | build-backend = "hatchling.build"
 4 | 
 5 | [project]
 6 | name = "mcp-linkedin"
 7 | version = "0.1.1"
 8 | description = "MCP server to interact with LinkedIn"
 9 | readme = "README.md"
10 | requires-python = ">=3.7"
11 | dependencies = [
12 |     "linkedin-api",
13 |     "fastmcp",
14 |     "requests",
15 |     "uvicorn",
16 | ]
17 | authors = [
18 |     { name = "Adhika Setya Pramudita", email = "[email protected]" }
19 | ]
20 | 
21 | [project.urls]
22 | Homepage = "https://github.com/adhikasp/mcp-linkedin"
23 | 
24 | [project.scripts]
25 | mcp-linkedin = "mcp_linkedin.client:mcp.run"
```

--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------

```yaml
 1 | # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml
 2 | 
 3 | startCommand:
 4 |   type: stdio
 5 |   configSchema:
 6 |     # JSON Schema defining the configuration options for the MCP.
 7 |     type: object
 8 |     required:
 9 |       - linkedinEmail
10 |       - linkedinPassword
11 |     properties:
12 |       linkedinEmail:
13 |         type: string
14 |         description: Your LinkedIn email address
15 |       linkedinPassword:
16 |         type: string
17 |         description: Your LinkedIn password
18 |   commandFunction:
19 |     # A function that produces the CLI command to start the MCP on stdio.
20 |     |-
21 |     (config) => ({command: 'uvicorn', args: ['mcp_linkedin.client:mcp.run', '--host', '0.0.0.0', '--port', '8000'], env: {LINKEDIN_EMAIL: config.linkedinEmail, LINKEDIN_PASSWORD: config.linkedinPassword}})
```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
 1 | # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
 2 | # Use the official Python image with a slim variant
 3 | FROM python:3.9-slim
 4 | 
 5 | # Set the working directory in the container
 6 | WORKDIR /app
 7 | 
 8 | # Copy the pyproject.toml file and src directory into the container
 9 | COPY pyproject.toml /app/
10 | COPY src /app/src
11 | 
12 | # Install the dependencies specified in the pyproject.toml
13 | RUN pip install --upgrade pip
14 | RUN pip install hatchling
15 | RUN pip install .
16 | 
17 | # Set environment variables for LinkedIn credentials
18 | # These should be set during container run or through a Docker secret mechanism
19 | ENV LINKEDIN_EMAIL=your_linkedin_email
20 | ENV LINKEDIN_PASSWORD=your_linkedin_password
21 | 
22 | # Set the entry point for the container
23 | ENTRYPOINT ["uvicorn", "mcp_linkedin.client:mcp.run", "--host", "0.0.0.0", "--port", "8000"]
```

--------------------------------------------------------------------------------
/src/mcp_linkedin/client.py:
--------------------------------------------------------------------------------

```python
 1 | from linkedin_api import Linkedin
 2 | from fastmcp import FastMCP
 3 | import os
 4 | import logging
 5 | 
 6 | mcp = FastMCP("mcp-linkedin")
 7 | logger = logging.getLogger(__name__)
 8 | 
 9 | def get_client():
10 |     return Linkedin(os.getenv("LINKEDIN_EMAIL"), os.getenv("LINKEDIN_PASSWORD"), debug=True)
11 | 
12 | @mcp.tool()
13 | def get_feed_posts(limit: int = 10, offset: int = 0) -> str:
14 |     """
15 |     Retrieve LinkedIn feed posts.
16 | 
17 |     :return: List of feed post details
18 |     """
19 |     client = get_client()
20 |     try:
21 |         post_urns = client.get_feed_posts(limit=limit, offset=offset)
22 |     except Exception as e:
23 |         logger.error(f"Error: {e}")
24 |         return f"Error: {e}"
25 |     
26 |     posts = ""
27 |     for urn in post_urns:
28 |         posts += f"Post by {urn["author_name"]}: {urn["content"]}\n"
29 | 
30 |     return posts
31 | 
32 | @mcp.tool()
33 | def search_jobs(keywords: str, limit: int = 3, offset: int = 0, location: str = '') -> str:
34 |     """
35 |     Search for jobs on LinkedIn.
36 |     
37 |     :param keywords: Job search keywords
38 |     :param limit: Maximum number of job results
39 |     :param location: Optional location filter
40 |     :return: List of job details
41 |     """
42 |     client = get_client()
43 |     jobs = client.search_jobs(
44 |         keywords=keywords,
45 |         location_name=location,
46 |         limit=limit,
47 |         offset=offset,
48 |     )
49 |     job_results = ""
50 |     for job in jobs:
51 |         job_id = job["entityUrn"].split(":")[-1]
52 |         job_data = client.get_job(job_id=job_id)
53 | 
54 |         job_title = job_data["title"]
55 |         company_name = job_data["companyDetails"]["com.linkedin.voyager.deco.jobs.web.shared.WebCompactJobPostingCompany"]["companyResolutionResult"]["name"]
56 |         job_description = job_data["description"]["text"]
57 |         job_location = job_data["formattedLocation"]
58 | 
59 |         job_results += f"Job by {job_title} at {company_name} in {job_location}: {job_description}\n\n"
60 | 
61 |     return job_results
62 | 
63 | if __name__ == "__main__":
64 |     print(search_jobs(keywords="data engineer", location="Jakarta", limit=2))
```