[
  {
    "path": ".gitignore",
    "content": "explore.py\n__pycache__"
  },
  {
    "path": ".python-version",
    "content": "3.13\n"
  },
  {
    "path": "Dockerfile",
    "content": "# Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile\n# Use the official Python image with a slim variant\nFROM python:3.9-slim\n\n# Set the working directory in the container\nWORKDIR /app\n\n# Copy the pyproject.toml file and src directory into the container\nCOPY pyproject.toml /app/\nCOPY src /app/src\n\n# Install the dependencies specified in the pyproject.toml\nRUN pip install --upgrade pip\nRUN pip install hatchling\nRUN pip install .\n\n# Set environment variables for LinkedIn credentials\n# These should be set during container run or through a Docker secret mechanism\nENV LINKEDIN_EMAIL=your_linkedin_email\nENV LINKEDIN_PASSWORD=your_linkedin_password\n\n# Set the entry point for the container\nENTRYPOINT [\"uvicorn\", \"mcp_linkedin.client:mcp.run\", \"--host\", \"0.0.0.0\", \"--port\", \"8000\"]"
  },
  {
    "path": "LICENSE",
    "content": "This is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <https://unlicense.org>\n"
  },
  {
    "path": "README.md",
    "content": "# MCP LinkedIn\n\nA Model Context Protocol (MCP) server that provides tools to interact with LinkedIn's Feeds and Job API.\n\nThis is using unofficial LinkedIn API via [Linkedin-api](https://github.com/tomquirk/linkedin-api). Use at your own risk.\n\n<a href=\"https://smithery.ai/server/mcp-linkedin\"><img alt=\"Smithery Badge\" src=\"https://smithery.ai/badge/mcp-linkedin\"></a>\n<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>\n\n### Installing via Smithery\n\nTo install LinkedIn Interaction Server for Claude Desktop automatically via [Smithery](https://smithery.ai/server/mcp-linkedin):\n\n```bash\nnpx -y @smithery/cli install mcp-linkedin --client claude\n```\n\n## Configuration\n\n```json\n{\n    \"mcpServers\": {\n        \"linkedin\": {\n            \"command\": \"uvx\",\n            \"args\": [\"--from\", \"git+https://github.com/adhikasp/mcp-linkedin\", \"mcp-linkedin\"],\n            \"env\": {\n                \"LINKEDIN_EMAIL\": \"your_linkedin_email\",\n                \"LINKEDIN_PASSWORD\": \"your_linkedin_password\"\n            }\n        }\n    }\n}\n```\n\n## Sample usage\n\nUsing [mcp-client-cli](https://github.com/adhikasp/mcp-client-cli)\n\n### Get feed posts\n\n```\n$ llm whats happening in linkedin feed? Do not mention names\n\nI'll retrieve the recent LinkedIn feed posts without mentioning any specific names.\n\nTool Calls:\n  get_feed_posts\n  Args:\n    limit: 10\n\nBased on the LinkedIn feed, here are the key highlights without mentioning specific names:\n\n1. Data Science & Cybersecurity Insights:\n   - A post about a massive dataset from a major tech company\n   - Includes 13 million pieces of evidence\n   - Covers SIEM telemetry from 6,100 organizations\n   - Represents 441 MITRE ATT&CK techniques\n\n2. DevOps Community Event:\n   - A local DevOps meetup was held at a tech company office\n   - Discussed topics like AWS Lambda, Kubernetes scaling, Terraform\n   - Highlighted the importance of networking and continuous learning\n   - Shared experiences of transitioning between tech roles\n\n3. Linux Engineering Perspectives:\n   - Insights into what makes a great Linux engineer\n   - Key skills include:\n     * Command-line troubleshooting\n     * Process management\n     * Networking fundamentals\n     * System architecture understanding\n     * Task automation\n     * Shell scripting\n\n4. Professional Networking:\n   - Some posts about job seeking\n   - Discussions about career transitions\n   - Sharing professional experiences and learnings\n\n5. Tech Community Reflections:\n   - Posts about inspirational figures\n   - Discussions on professional growth\n   - Reflections on learning and personal development\n\nThe feed showcases a mix of technical insights, professional networking, career development, and community engagement across various tech domains.\n```\n\n### Search for jobs\n\n```\n$ 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\n\nI'll help you find data engineer jobs in Jakarta and analyze them against your resume. I'll break this down into steps:\n\n1. First, I'll search for data engineer jobs in Jakarta\n2. Then, I'll read your resume\n3. Finally, I'll analyze the job matches\n\nLet's start by searching for jobs:\n\nTool Calls:\n  search_jobs\n  Args:\n    keywords: data engineer\n    location: Jakarta\n    limit: 3\n\n\nNow, I'll read your resume:\n\nTool Calls:\n  read_file\n  Args:\n    path: resume.md\nSecure MCP Filesystem Server running on stdio\nAllowed directories: [ '/home/adhikasp', '/mnt/e' ]\n\n\nNow, I'll analyze the jobs against your resume:\n\n1. Job in Financial Technology Sector (Lead Backend Engineer):\n   - Match Score: 85%\n   - Strengths:\n     * Requires experience in developing scalable microservices (aligns with your Grab experience)\n     * Strong focus on cloud infrastructure (AWS, GCP) - matches your cloud skills\n     * Requires experience with event-driven architecture and message brokers\n     * Requires Go or Python programming (your proficient languages)\n   - Potential Gaps:\n     * Specific focus on credit risk and fraud detection might require additional domain knowledge\n     * Emphasis on team leadership (6+ years experience leading teams)\n\n2. Job in Financial Technology Sector (DevOps Engineer):\n   - Match Score: 75%\n   - Strengths:\n     * Requires cloud platform experience (AWS, GCP)\n     * Needs containerization skills (Docker, Kubernetes)\n     * Requires scripting in Python and Bash\n     * Needs infrastructure as code experience\n   - Potential Gaps:\n     * More DevOps focused compared to your backend engineering background\n     * Specific monitoring tools might require additional learning\n\n3. Job in Enterprise Collaboration Software (Solution Engineer):\n   - Match Score: 60%\n   - Strengths:\n     * Requires strong communication skills\n     * Technical consulting background\n     * Experience with enterprise software\n   - Potential Gaps:\n     * Less technical compared to your current role\n     * More sales-oriented solution engineering\n     * Less hands-on technical development\n\nRecommendation:\nThe 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.\n\nWould you like me to elaborate on any of these job analyses or provide more detailed insights?\n```\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[build-system]\nrequires = [\"hatchling\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"mcp-linkedin\"\nversion = \"0.1.1\"\ndescription = \"MCP server to interact with LinkedIn\"\nreadme = \"README.md\"\nrequires-python = \">=3.7\"\ndependencies = [\n    \"linkedin-api\",\n    \"fastmcp\",\n    \"requests\",\n    \"uvicorn\",\n]\nauthors = [\n    { name = \"Adhika Setya Pramudita\", email = \"adhika.setya.p@gmail.com\" }\n]\n\n[project.urls]\nHomepage = \"https://github.com/adhikasp/mcp-linkedin\"\n\n[project.scripts]\nmcp-linkedin = \"mcp_linkedin.client:mcp.run\""
  },
  {
    "path": "smithery.yaml",
    "content": "# Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml\n\nstartCommand:\n  type: stdio\n  configSchema:\n    # JSON Schema defining the configuration options for the MCP.\n    type: object\n    required:\n      - linkedinEmail\n      - linkedinPassword\n    properties:\n      linkedinEmail:\n        type: string\n        description: Your LinkedIn email address\n      linkedinPassword:\n        type: string\n        description: Your LinkedIn password\n  commandFunction:\n    # A function that produces the CLI command to start the MCP on stdio.\n    |-\n    (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}})"
  },
  {
    "path": "src/mcp_linkedin/__init__.py",
    "content": ""
  },
  {
    "path": "src/mcp_linkedin/client.py",
    "content": "from linkedin_api import Linkedin\nfrom fastmcp import FastMCP\nimport os\nimport logging\n\nmcp = FastMCP(\"mcp-linkedin\")\nlogger = logging.getLogger(__name__)\n\ndef get_client():\n    return Linkedin(os.getenv(\"LINKEDIN_EMAIL\"), os.getenv(\"LINKEDIN_PASSWORD\"), debug=True)\n\n@mcp.tool()\ndef get_feed_posts(limit: int = 10, offset: int = 0) -> str:\n    \"\"\"\n    Retrieve LinkedIn feed posts.\n\n    :return: List of feed post details\n    \"\"\"\n    client = get_client()\n    try:\n        post_urns = client.get_feed_posts(limit=limit, offset=offset)\n    except Exception as e:\n        logger.error(f\"Error: {e}\")\n        return f\"Error: {e}\"\n    \n    posts = \"\"\n    for urn in post_urns:\n        posts += f\"Post by {urn[\"author_name\"]}: {urn[\"content\"]}\\n\"\n\n    return posts\n\n@mcp.tool()\ndef search_jobs(keywords: str, limit: int = 3, offset: int = 0, location: str = '') -> str:\n    \"\"\"\n    Search for jobs on LinkedIn.\n    \n    :param keywords: Job search keywords\n    :param limit: Maximum number of job results\n    :param location: Optional location filter\n    :return: List of job details\n    \"\"\"\n    client = get_client()\n    jobs = client.search_jobs(\n        keywords=keywords,\n        location_name=location,\n        limit=limit,\n        offset=offset,\n    )\n    job_results = \"\"\n    for job in jobs:\n        job_id = job[\"entityUrn\"].split(\":\")[-1]\n        job_data = client.get_job(job_id=job_id)\n\n        job_title = job_data[\"title\"]\n        company_name = job_data[\"companyDetails\"][\"com.linkedin.voyager.deco.jobs.web.shared.WebCompactJobPostingCompany\"][\"companyResolutionResult\"][\"name\"]\n        job_description = job_data[\"description\"][\"text\"]\n        job_location = job_data[\"formattedLocation\"]\n\n        job_results += f\"Job by {job_title} at {company_name} in {job_location}: {job_description}\\n\\n\"\n\n    return job_results\n\nif __name__ == \"__main__\":\n    print(search_jobs(keywords=\"data engineer\", location=\"Jakarta\", limit=2))"
  }
]