feat(tools): add get_my_profile, search_companies, get_company_employees#386
Conversation
- 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 SummaryThis PR adds three new MCP tools —
Confidence Score: 5/5Safe 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
Sequence DiagramsequenceDiagram
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
Reviews (2): Last reviewed commit: "fix(get_my_profile): resolve real userna..." | Re-trigger Greptile |
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.
|
@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! |
Summary
get_my_profileto let agents fetch the authenticated user's ownprofile without knowing their username — navigates to
/in/me/whichLinkedIn redirects to the real profile; resolved URL reveals the actual
username. Supports the same
sectionsandmax_scrollsparameters asget_person_profile.search_companiesto search LinkedIn companies by keyword, directlymirroring the existing
search_peoplepattern and return format.get_company_employeesto list employees from/company/{name}/people/with an optionalkeywordsfilter 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_MSGsentinel patternAuthenticationErrordouble-catch withhandle_auth_errorreadOnlyHint/openWorldHintannotationsexclude_args=["extractor"]for test injectionscraping/extractor.py, tools registered intools/person.pyandtools/company.pyChecklist
scraping/extractor.py)tools/person.py,tools/company.py)_make_mock_extractor(tests/test_tools.py)TestToolTimeoutsupdated with new tool namesREADME.mdtool table updateddocs/docker-hub.mdfeatures list updatedmanifest.jsontools array updateduv run pytest— 41 passeduv run ruff check . && uv run ruff format --check .— cleanuv run ty check— cleanSynthetic prompt