Skip to content

feat(tools): add get_my_profile, search_companies, get_company_employees#386

Open
Hovo-Dev wants to merge 2 commits intostickerdaniel:mainfrom
Hovo-Dev:feature/add-get-my-profile-search-companies-employees
Open

feat(tools): add get_my_profile, search_companies, get_company_employees#386
Hovo-Dev wants to merge 2 commits intostickerdaniel:mainfrom
Hovo-Dev:feature/add-get-my-profile-search-companies-employees

Conversation

@Hovo-Dev
Copy link
Copy Markdown

@Hovo-Dev Hovo-Dev commented Apr 22, 2026

Summary

  • Adds get_my_profile to let agents fetch the authenticated user's own
    profile without knowing their username — navigates to /in/me/ which
    LinkedIn redirects to the real profile; resolved URL reveals the actual
    username. Supports the same sections and max_scrolls parameters as
    get_person_profile.
  • Adds search_companies to search LinkedIn companies by keyword, directly
    mirroring the existing search_people pattern and return format.
  • Adds get_company_employees to list employees from
    /company/{name}/people/ with an optional keywords filter by name,
    title, or skill — useful for "who do I know at X?" workflows. Returns
    /in/ references for each listed employee.

Implementation notes

All three tools follow existing conventions exactly:

  • extract_page + _RATE_LIMITED_MSG sentinel pattern
  • AuthenticationError double-catch with handle_auth_error
  • readOnlyHint / openWorldHint annotations
  • exclude_args=["extractor"] for test injection
  • Extractor methods added to scraping/extractor.py, tools registered in
    tools/person.py and tools/company.py

Checklist

  • Extractor methods added (scraping/extractor.py)
  • Tools registered (tools/person.py, tools/company.py)
  • Mock methods added to _make_mock_extractor (tests/test_tools.py)
  • Test classes added (11 new tests, all passing)
  • TestToolTimeouts updated with new tool names
  • README.md tool table updated
  • docs/docker-hub.md features list updated
  • manifest.json tools array updated
  • uv run pytest — 41 passed
  • uv run ruff check . && uv run ruff format --check . — clean
  • uv run ty check — clean

Synthetic prompt

Add three new MCP tools — get_my_profile (authenticated user's own
profile via /in/me/), search_companies (company keyword search
mirroring search_people), and get_company_employees (employee list
from /company/{name}/people/ with optional keyword filter). Follow the
existing extract_page + _RATE_LIMITED_MSG pattern, add extractor
methods, register tools, wire tests with mock injection, and update
README, docker-hub docs, and manifest per CONTRIBUTING.md checklist.

- get_my_profile: scrape the authenticated user's own profile via
  /in/me/ redirect; supports same sections/max_scrolls as
  get_person_profile; resolved URL reveals real username
- search_companies: search LinkedIn companies by keyword, mirroring
  the existing search_people pattern
- get_company_employees: list employees from /company/{name}/people/
  with optional keyword filter by name, title, or skill

Each tool follows the existing conventions: extract_page +
_RATE_LIMITED_MSG sentinel, AuthenticationError handling,
readOnlyHint/openWorldHint annotations, exclude_args=["extractor"]
for test injection. Tests, README, docker-hub docs, and manifest
updated per CONTRIBUTING.md checklist.
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 22, 2026

Greptile Summary

This PR adds three new MCP tools — get_my_profile, search_companies, and get_company_employees — all following the existing extract_page + _RATE_LIMITED_MSG sentinel pattern, with correct AuthenticationError double-catch, readOnlyHint/openWorldHint annotations, exclude_args=[\"extractor\"] for test injection, and full README/manifest/docker-hub updates.

get_my_profile addresses the previously resolved URL-resolution concern by first navigating to /in/me/ to capture the post-redirect URL, extracting the real username via regex, and delegating to scrape_person — an improvement over always returning /in/me/. search_companies mirrors search_people exactly, and get_company_employees correctly uses quote_plus for the keyword query parameter.

Confidence Score: 5/5

Safe to merge — all three tools follow established conventions with no logic errors, correct error handling, and comprehensive test coverage.

No P0 or P1 findings. All new tools mirror existing patterns (extract_page + _RATE_LIMITED_MSG, AuthenticationError double-catch, readOnlyHint/openWorldHint, exclude_args injection). Tests cover success, sections, callbacks, unknown sections, and error paths. Docs and manifest are fully updated.

No files require special attention.

Important Files Changed

Filename Overview
linkedin_mcp_server/scraping/extractor.py Adds get_my_profile, get_company_employees, and search_companies extractor methods; all follow existing patterns and correctly handle rate-limit sentinel, errors, and references
linkedin_mcp_server/tools/company.py Registers search_companies and get_company_employees tools; correct error handling, progress reporting, and tool annotations
linkedin_mcp_server/tools/person.py Registers get_my_profile tool; correctly uses parse_person_sections, passes callbacks, and handles unknown section names
tests/test_tools.py Adds 11 new tests covering success, section selection, callbacks, unknown sections, and error paths for all three new tools
manifest.json Adds manifest entries for get_my_profile, search_companies, and get_company_employees

Sequence Diagram

sequenceDiagram
    participant Agent
    participant Tool as MCP Tool Layer
    participant Extractor as LinkedInExtractor
    participant Browser as Playwright
    participant LI as LinkedIn

    Note over Agent,LI: get_my_profile flow
    Agent->>Tool: get_my_profile(sections)
    Tool->>Extractor: get_my_profile(sections, callbacks)
    Extractor->>Browser: navigate /in/me/
    Browser->>LI: GET /in/me/
    LI-->>Browser: redirect to real profile
    Browser-->>Extractor: page.url = real profile URL
    Extractor->>Extractor: regex extract real username
    Extractor->>Browser: scrape_person with real username
    Browser->>LI: GET each section URL
    LI-->>Browser: page content
    Extractor-->>Agent: url + sections dict

    Note over Agent,LI: search_companies flow
    Agent->>Tool: search_companies(keywords)
    Tool->>Extractor: search_companies(keywords)
    Extractor->>Browser: extract_page search URL
    Browser->>LI: GET company search
    LI-->>Browser: results page
    Extractor-->>Agent: url + search_results section

    Note over Agent,LI: get_company_employees flow
    Agent->>Tool: get_company_employees(company, kw)
    Tool->>Extractor: get_company_employees(company, kw)
    Extractor->>Browser: extract_page /company/name/people/
    Browser->>LI: GET employees page
    LI-->>Browser: employees list
    Extractor-->>Agent: url + employees section + references
Loading

Reviews (2): Last reviewed commit: "fix(get_my_profile): resolve real userna..." | Re-trigger Greptile

Comment thread linkedin_mcp_server/scraping/extractor.py
scrape_person builds result["url"] from the static base_url, not the
post-redirect page URL. Navigate to /in/me/ first, read self._page.url
after the redirect, extract the real username via regex, then pass it
to scrape_person so result["url"] reflects the actual profile URL
rather than /in/me/. Update docstrings accordingly.
@Hovo-Dev
Copy link
Copy Markdown
Author

@stickerdaniel Thank you for building and maintaining this — it's genuinely one of the most useful MCP servers out there that I use everyday for researching through my background AI agents.

I put together a few tools that I think would be a great addition: get_my_profile to let agents know who they're acting as, search_companies to find companies by keyword, and get_company_employees to list people at a company with an optional filter. I'm actively running AI agents that research LinkedIn and I kept hitting the wall without these — having them would make a real difference both for my workflows and for others who use this on a daily basis.

Would really appreciate your review and a merge if it looks good to you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant