README: add Used-by section#452
Conversation
Greptile SummaryThis PR adds LinkedIn posting actions and surfaces company post permalinks for downstream use. It changes:
Confidence Score: 3/5This should wait until the posting URL contract is fixed.
linkedin_mcp_server/scraping/extractor.py Important Files Changed
Prompt To Fix All With AIFix the following 3 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 3
linkedin_mcp_server/scraping/extractor.py:418-428
**Normalize probed hrefs**
This probe only accepts paths that already start with `/posts/` or `/feed/update/`. If LinkedIn exposes the same anchors as absolute URLs, such as `https://www.linkedin.com/posts/...`, this filter drops them and `get_company_posts` still returns no per-post references. The rest of the extractor already canonicalizes anchors through `anchor.href`, so this path should parse the href against the current origin before matching the pathname.
### Issue 2 of 3
linkedin_mcp_server/scraping/extractor.py:3545
**Accept relative permalinks**
`get_feed` and the new company-post reference path return LinkedIn post references as relative URLs like `/posts/...` and `/feed/update/...`, but this method passes `post_url` straight to `page.goto`. A caller that uses the returned reference with `post_comment` will fail navigation before reaching the post. Normalize relative LinkedIn paths to `https://www.linkedin.com...` before calling `_navigate_to_page`.
### Issue 3 of 3
linkedin_mcp_server/scraping/extractor.py:3890
**Accept relative permalinks**
The post references produced by `get_feed` and `get_company_posts` are relative LinkedIn paths, but `react_to_post` sends `post_url` directly into navigation. When a client passes `/posts/...` or `/feed/update/...` from those references, Playwright receives a URL with no scheme and the reaction flow never reaches the post. Normalize relative LinkedIn paths before navigating.
Reviews (3): Last reviewed commit: "feat(company): promote per-post permalin..." | Re-trigger Greptile |
…gate Mirrors messaging.send_message pattern: FastMCP destructive write, JS-based composer focus + keyboard.type + JS submit click to bypass Patchright actionability. Falls back to clicking the Comment action button if the inline composer isn't visible. Verifies success by polling for the typed comment text in the DOM.
…rm, dispatch input event LinkedIn's comment submit button is labeled 'Comment' not 'Post'; the original selector aria-label*='Post' never matched. Also Quill editor needed an explicit input event after keyboard.type to mark the comment non-empty. Submit selector now scopes to the composer's parent form/container to avoid hitting the feed-level Comment action button. Returns diagnostic info on failure (candidate count + disabled states) for the next failure mode.
…in response Search all Comment/Post-labeled buttons globally and pick the one closest to the input by vertical position, so we handle composers whose parent form doesn't wrap the submit. Add Ctrl+Enter fallback in case the click path is blocked. Surface the JS-side diagnostic (candidate count, disabled states, text, classes) in the tool response so the caller sees what's on the page without grepping server logs.
…scan LinkedIn empties the contenteditable on successful submit, which is a more reliable signal than scraping the comment thread for the typed text (comment-item class names drift across UI revisions). Primary signal is now composerEmpty; secondary is text-visible in any comment-container class, excluding the composer itself to avoid false-positives when the composer didn't clear.
| if already_pressed and norm_reaction == "like": | ||
| return self._react_result( | ||
| self._page.url, | ||
| "already_reacted", | ||
| "Post already has the Like reaction applied. No change made.", | ||
| reaction=norm_reaction, | ||
| applied=True, | ||
| ) |
There was a problem hiding this comment.
This branch treats any active reaction as an existing Like. LinkedIn marks the reaction button active for Love, Celebrate, Support, and other reactions too, so calling react_to_post(..., reaction="like") on a post that currently has Love returns already_reacted with applied=True without changing it to Like. The short-circuit needs to verify the current reaction is actually Like before skipping the click.
Prompt To Fix With AI
This is a comment left during a code review.
Path: linkedin_mcp_server/scraping/extractor.py
Line: 3902-3909
Comment:
**Check reaction type**
This branch treats any active reaction as an existing Like. LinkedIn marks the reaction button active for Love, Celebrate, Support, and other reactions too, so calling `react_to_post(..., reaction="like")` on a post that currently has Love returns `already_reacted` with `applied=True` without changing it to Like. The short-circuit needs to verify the current reaction is actually Like before skipping the click.
How can I resolve this? If you propose a fix, please make it concise.…ost_comment/react_to_post can target peer posts from get_company_posts results
| // /posts/<slug>-<digits>-<suffix> | ||
| // /feed/update/urn:li:activity:<digits>/ | ||
| const anchors = Array.from(main.querySelectorAll('a[href]')); | ||
| const out = []; | ||
| const seen = new Set(); | ||
| for (const a of anchors) { | ||
| const href = a.getAttribute('href') || ''; | ||
| if (!href) continue; | ||
| // Strip query string and trailing slash for dedup parity | ||
| const noQuery = href.split('?')[0]; | ||
| const isPostPath = |
There was a problem hiding this comment.
This probe only accepts paths that already start with /posts/ or /feed/update/. If LinkedIn exposes the same anchors as absolute URLs, such as https://www.linkedin.com/posts/..., this filter drops them and get_company_posts still returns no per-post references. The rest of the extractor already canonicalizes anchors through anchor.href, so this path should parse the href against the current origin before matching the pathname.
Prompt To Fix With AI
This is a comment left during a code review.
Path: linkedin_mcp_server/scraping/extractor.py
Line: 418-428
Comment:
**Normalize probed hrefs**
This probe only accepts paths that already start with `/posts/` or `/feed/update/`. If LinkedIn exposes the same anchors as absolute URLs, such as `https://www.linkedin.com/posts/...`, this filter drops them and `get_company_posts` still returns no per-post references. The rest of the extractor already canonicalizes anchors through `anchor.href`, so this path should parse the href against the current origin before matching the pathname.
How can I resolve this? If you propose a fix, please make it concise.| comment_text: Body of the comment to post. | ||
| confirm_send: Must be True to actually submit the comment. | ||
| """ | ||
| await self._navigate_to_page(post_url) |
There was a problem hiding this comment.
get_feed and the new company-post reference path return LinkedIn post references as relative URLs like /posts/... and /feed/update/..., but this method passes post_url straight to page.goto. A caller that uses the returned reference with post_comment will fail navigation before reaching the post. Normalize relative LinkedIn paths to https://www.linkedin.com... before calling _navigate_to_page.
Prompt To Fix With AI
This is a comment left during a code review.
Path: linkedin_mcp_server/scraping/extractor.py
Line: 3545
Comment:
**Accept relative permalinks**
`get_feed` and the new company-post reference path return LinkedIn post references as relative URLs like `/posts/...` and `/feed/update/...`, but this method passes `post_url` straight to `page.goto`. A caller that uses the returned reference with `post_comment` will fail navigation before reaching the post. Normalize relative LinkedIn paths to `https://www.linkedin.com...` before calling `_navigate_to_page`.
How can I resolve this? If you propose a fix, please make it concise.| reaction=norm_reaction, | ||
| ) | ||
|
|
||
| await self._navigate_to_page(post_url) |
There was a problem hiding this comment.
The post references produced by get_feed and get_company_posts are relative LinkedIn paths, but react_to_post sends post_url directly into navigation. When a client passes /posts/... or /feed/update/... from those references, Playwright receives a URL with no scheme and the reaction flow never reaches the post. Normalize relative LinkedIn paths before navigating.
Prompt To Fix With AI
This is a comment left during a code review.
Path: linkedin_mcp_server/scraping/extractor.py
Line: 3890
Comment:
**Accept relative permalinks**
The post references produced by `get_feed` and `get_company_posts` are relative LinkedIn paths, but `react_to_post` sends `post_url` directly into navigation. When a client passes `/posts/...` or `/feed/update/...` from those references, Playwright receives a URL with no scheme and the reaction flow never reaches the post. Normalize relative LinkedIn paths before navigating.
How can I resolve this? If you propose a fix, please make it concise.
Adding a link to a project built on top of this MCP server.
till-hohmann/tinkering - linkedin-engagement-console is a daily LinkedIn engagement console with grounded drafting. It uses this MCP server as the LinkedIn data layer.
Happy to adjust the wording or move it elsewhere in the README if you'd prefer a different spot. Thanks for shipping this, the Patchright stealth approach made it possible.