Open-source MCP server for LinkedIn. Give Claude and any MCP-compatible AI agent access to profiles, companies, jobs, and messages.
This report presents the forensic synthetic code analysis of stickerdaniel/linkedin-mcp-server, a Python project with 3,061 GitHub stars. SynthScan v2.0 examined 69,250 lines of code across 156 source files, recording 2248 pattern matches distributed across 18 syntactic categories. The overall adjusted score of 34.0 places this repository in the Strong AI signal band.
The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).
Longitudinal tracking requires multiple scan runs. Once this repository is re-scanned after new commits land, this chart will visualise how the synthetic code signal evolves over time — enabling you to detect whether AI authorship is growing, stabilising, or being actively corrected by human engineers.
Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.
This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.
The scanner identified 2248 distinct pattern matches across 18 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | linkedin_mcp_server/bootstrap.py | 132 | def reset_bootstrap_for_testing() -> None: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 173 | def configure_browser_environment() -> Path: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 196 | def _patchright_install_targets() -> dict[str, str] | None: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 258 | async def start_background_browser_setup_if_needed() -> None: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 365 | def _start_browser_setup_task_locked() -> None: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 451 | async def _ensure_browser_installed() -> None: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 490 | async def _refresh_background_task_state() -> None: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 528 | async def ensure_tool_ready_or_raise( | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 593 | def _raise_if_docker_auth_missing() -> None: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 694 | async def _announce_auto_import_once(ctx: Context | None) -> None: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 1053 | async def invalidate_auth_and_trigger_relogin( | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 1220 | def _force_move_auth_state_aside( | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 1227 | def _move_invalid_auth_state_aside( | CODE |
| LOW | linkedin_mcp_server/error_diagnostics.py | 102 | def format_tool_error_with_diagnostics( | CODE |
| LOW | linkedin_mcp_server/error_diagnostics.py | 264 | def _public_issue_diagnostics( | CODE |
| LOW⚡ | linkedin_mcp_server/error_diagnostics.py | 356 | def _inside_running_event_loop() -> bool: | CODE |
| LOW⚡ | linkedin_mcp_server/error_diagnostics.py | 364 | def _installation_method_lines(runtime: dict[str, Any]) -> list[str]: | CODE |
| LOW⚡ | linkedin_mcp_server/error_diagnostics.py | 374 | def _installation_method_summary(runtime: dict[str, Any]) -> str: | CODE |
| LOW | linkedin_mcp_server/greenlet_runtime.py | 69 | def _the_runtime_cannot_be_loaded() -> bool: | CODE |
| LOW | linkedin_mcp_server/greenlet_runtime.py | 133 | def explain_a_missing_runtime() -> None: | CODE |
| LOW | linkedin_mcp_server/daemon_owner.py | 616 | def _forget_superseded_tokens(auth_root: Path, *, keeping: str) -> None: | CODE |
| LOW | linkedin_mcp_server/hidden_target.py | 56 | def hidden_target_is_supported() -> bool: | CODE |
| LOW | linkedin_mcp_server/hidden_target.py | 112 | def attaching_to_other_targets(): | CODE |
| LOW | linkedin_mcp_server/daemon_proxy.py | 185 | def _no_connection_was_established(exc: BaseException) -> bool: | CODE |
| LOW | linkedin_mcp_server/daemon_proxy.py | 286 | def _tells_which_owner_failed() -> type: | CODE |
| LOW | linkedin_mcp_server/daemon_proxy.py | 368 | async def list_resource_templates_mcp(self, *args: Any, **kwargs: Any) -> Any: | CODE |
| LOW | linkedin_mcp_server/daemon_proxy.py | 648 | async def on_list_resource_templates( | CODE |
| LOW | linkedin_mcp_server/session_state.py | 132 | def runtime_storage_state_path( | CODE |
| LOW | linkedin_mcp_server/session_state.py | 308 | def _cgroup_path_is_containerised(path: Path) -> bool: | CODE |
| LOW | linkedin_mcp_server/session_state.py | 947 | def _restore_source_profile_locked(backup_dir: Path, profile_dir: Path) -> bool: | CODE |
| LOW | linkedin_mcp_server/daemon_election.py | 586 | def _start_contending_for_the_lock( | CODE |
| LOW | linkedin_mcp_server/debug_trace.py | 98 | def reset_trace_state_for_testing() -> None: | CODE |
| LOW | linkedin_mcp_server/daemon_liveness.py | 273 | def reset_liveness_for_testing() -> None: | CODE |
| LOW | linkedin_mcp_server/cli_main.py | 52 | def choose_transport_interactive() -> Literal["stdio", "streamable-http"]: | CODE |
| LOW | linkedin_mcp_server/cli_main.py | 136 | def import_from_browser_and_exit() -> None: | CODE |
| LOW | linkedin_mcp_server/private_state.py | 478 | def _verify_no_extended_acl_fd(fd: int, path: Path) -> None: | CODE |
| LOW | linkedin_mcp_server/setup.py | 153 | async def _login_holding_the_profile( | CODE |
| LOW | linkedin_mcp_server/setup.py | 212 | async def _login_into_fresh_profile( | CODE |
| LOW | linkedin_mcp_server/windows_acl.py | 407 | def _require_acl_capable_volume(path: Path) -> None: | CODE |
| LOW | linkedin_mcp_server/authentication.py | 23 | def get_authentication_source() -> bool: | CODE |
| LOW⚡ | linkedin_mcp_server/error_handler.py | 51 | def _raise_tool_error_with_diagnostics( | CODE |
| LOW | linkedin_mcp_server/server_role.py | 133 | def ask_this_process_to_stand_down(why: str) -> None: | CODE |
| LOW | linkedin_mcp_server/server_role.py | 153 | def a_held_profile_means_this_owner_must_go(lease: Any | None = None) -> None: | CODE |
| LOW | linkedin_mcp_server/server_role.py | 208 | def reset_process_role_for_testing() -> None: | CODE |
| LOW | linkedin_mcp_server/browser_downgrade.py | 209 | def a_version_can_be_asked_for() -> bool: | CODE |
| LOW | linkedin_mcp_server/browser_downgrade.py | 236 | def _the_line_that_should_carry_it(text: str) -> str: | CODE |
| LOW | linkedin_mcp_server/dependencies.py | 42 | def _is_linux_browser_dependency_error(error: Exception) -> bool: | CODE |
| LOW | linkedin_mcp_server/dependencies.py | 54 | def _is_browser_binary_missing_error(error: Exception) -> bool: | CODE |
| LOW | linkedin_mcp_server/daemon_auth.py | 76 | def _how_long_to_wait_for_the_sign_in(budget: float, already_spent: float) -> float: | CODE |
| LOW | linkedin_mcp_server/daemon_auth.py | 95 | def _what_is_left_of_this_call(budget: float, already_spent: float) -> float: | CODE |
| LOW | linkedin_mcp_server/daemon_auth.py | 207 | def _browser_still_holds_the_profile() -> bool: | CODE |
| LOW | linkedin_mcp_server/daemon_auth.py | 353 | async def a_repeat_could_change_something( | CODE |
| LOW | linkedin_mcp_server/profile_lease.py | 70 | def _windows_failure_is_contention(error_code: int) -> bool: | CODE |
| LOW | linkedin_mcp_server/profile_lease.py | 616 | def _discard_inherited_leases() -> None: | CODE |
| LOW | linkedin_mcp_server/debug_utils.py | 12 | def debug_stabilize_navigation_enabled() -> bool: | CODE |
| LOW | linkedin_mcp_server/browser_import/__init__.py | 29 | def import_session_from_browser( | CODE |
| LOW | linkedin_mcp_server/browser_import/orchestrate.py | 193 | async def import_session_from_browser( | CODE |
| LOW | linkedin_mcp_server/browser_import/orchestrate.py | 272 | async def _import_holding_the_profile( | CODE |
| LOW | linkedin_mcp_server/browser_import/extract.py | 111 | def _macos_safe_storage_password(account: str, service: str) -> bytes: | CODE |
| LOW | linkedin_mcp_server/browser_import/extract.py | 154 | def _linux_safe_storage_password(app_token: str) -> bytes: | CODE |
| 1565 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | linkedin_mcp_server/browser_import/extract.py | 246 | Layout: ``b'v10' || nonce(12) || ciphertext || tag(16)``. Store version >= 24 | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 211 | while (el && el !== main) { | CODE |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 214 | if (interactive >= 2 && buttons >= 1) { | CODE |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 220 | return null; | CODE |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 258 | const scope = main.querySelector('section') || main.firstElementChild || main; | CODE |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 262 | while (el && el !== scope && el !== main) { | CODE |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 278 | matches.push(el); | CODE |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 288 | return matches.length === 1 ? matches[0] : null; | CODE |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 331 | if (!main) return null; | CODE |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 1118 | return dialog?.innerText || dialog?.textContent || link?.innerText || ''; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2329 | if (!anchor) return null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2330 | return anchor.getAttribute('href') || anchor.href || null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2330 | return anchor.getAttribute('href') || anchor.href || null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2372 | if (!href) return null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2374 | if (idx === -1) return null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2378 | return username ? '/in/' + username + '/' : null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2387 | heading.innerText || heading.textContent | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2396 | for (let depth = 0; container && depth < 5; depth++) { | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2410 | profileLinks.push(path); | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2415 | let showAll = null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2418 | a.innerText || a.textContent | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2421 | showAll = a.href || a.getAttribute('href'); | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2475 | if (!href) return null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2477 | if (idx === -1) return null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2481 | return username ? '/in/' + username + '/' : null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2491 | links.push(path); | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2528 | if (!anchor) return null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2529 | return anchor.getAttribute('href') || anchor.href || null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2529 | return anchor.getAttribute('href') || anchor.href || null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2545 | heading.innerText || heading.textContent || '' | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2614 | const text = normalize(element.innerText || element.textContent); | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2615 | return text.length > 0 && text !== 'new message'; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2620 | normalize(element.innerText || element.textContent) === candidate | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 2630 | normalize(element.innerText || element.textContent).includes(candidate) | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4311 | element.matches && element.matches(headingSelector) | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4315 | : null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4317 | return normalize(heading?.innerText || heading?.textContent); | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4321 | let sibling = node?.previousElementSibling || null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4321 | let sibling = node?.previousElementSibling || null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4322 | for (let index = 0; sibling && index < 3; index += 1) { | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4350 | const heading = ownHeading || previousHeading; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4358 | for (let depth = 0; current && depth < 4; depth += 1) { | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4366 | current = current.parentElement?.closest(containerSelector) || null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4375 | if (!rawHref || rawHref === '#') { | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4376 | return null; | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4381 | : (anchor.href || rawHref); | STRING |
| HIGH⚡ | linkedin_mcp_server/scraping/extractor.py | 4385 | text: normalize(anchor.innerText || anchor.textContent), | STRING |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 2594 | (element.offsetWidth || element.offsetHeight || element.getClientRects().length) | STRING |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 2728 | normalize(element.innerText || element.textContent || ''), | STRING |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 2735 | entries.some(entry => entry === candidate || entry.includes(candidate)) | STRING |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 3071 | ids.push(match[1]); | STRING |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 3181 | return el ? el.textContent.trim() : null; | STRING |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 3479 | if (!buttons.length) return null; | STRING |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 3483 | return nums.length ? Math.max(...nums) : null; | STRING |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 3908 | const cap = (limit == null) | STRING |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 3925 | if (wanted && rowName !== wanted) continue; | STRING |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 3945 | results.push({ ariaLabel, threadId: match[1] }); | STRING |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 4267 | )).find(b => !b.disabled && (b.offsetWidth || b.offsetHeight || b.getClientRects().length)); | STRING |
| HIGH | linkedin_mcp_server/scraping/extractor.py | 4336 | const container = root || document.body; | STRING |
| HIGH | linkedin_mcp_server/core/utils.py | 117 | while (container && container !== document.body) { | STRING |
| 12 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL | linkedin_mcp_server/bootstrap.py | 867 | from linkedin_mcp_server.core.exceptions import ProxyConnectionError | CODE |
| CRITICAL | linkedin_mcp_server/dependencies.py | 17 | from linkedin_mcp_server.core.exceptions import AuthenticationError, NetworkError | CODE |
| CRITICAL | linkedin_mcp_server/tools/post.py | 19 | from linkedin_mcp_server.core.exceptions import AuthenticationError | CODE |
| CRITICAL | linkedin_mcp_server/tools/person.py | 17 | from linkedin_mcp_server.core.exceptions import AuthenticationError | CODE |
| CRITICAL | linkedin_mcp_server/tools/company.py | 15 | from linkedin_mcp_server.core.exceptions import AuthenticationError | CODE |
| CRITICAL | linkedin_mcp_server/tools/job.py | 14 | from linkedin_mcp_server.core.exceptions import AuthenticationError | CODE |
| CRITICAL | linkedin_mcp_server/tools/feed.py | 18 | from linkedin_mcp_server.core.exceptions import AuthenticationError | CODE |
| CRITICAL⚡ | tests/test_profile_lease_integration.py | 83 | from linkedin_mcp_server.core.exceptions import AuthenticationError | CODE |
| CRITICAL | tests/test_browser_driver.py | 11 | from linkedin_mcp_server.core.exceptions import ProxyConnectionError | CODE |
| CRITICAL | tests/test_proxy_errors.py | 6 | from linkedin_mcp_server.core.exceptions import NetworkError, ProxyConnectionError | CODE |
| CRITICAL | tests/test_scraping.py | 246 | from linkedin_mcp_server.core.exceptions import RateLimitError | CODE |
| CRITICAL | tests/test_core_auth.py | 7 | from linkedin_mcp_server.core.exceptions import AuthenticationError | CODE |
| CRITICAL | tests/test_bootstrap.py | 36 | from linkedin_mcp_server.core.exceptions import NetworkError | CODE |
| CRITICAL | tests/test_bootstrap.py | 1917 | from linkedin_mcp_server.core.exceptions import ProxyConnectionError | CODE |
| CRITICAL | tests/test_core_utils.py | 7 | from linkedin_mcp_server.core.exceptions import RateLimitError | CODE |
| CRITICAL | tests/test_tools.py | 205 | from linkedin_mcp_server.core.exceptions import AuthenticationError | CODE |
| CRITICAL | tests/test_tools.py | 428 | from linkedin_mcp_server.core.exceptions import AuthenticationError | CODE |
| CRITICAL⚡ | tests/test_error_handler.py | 144 | from linkedin_mcp_server.core.exceptions import AuthenticationError | CODE |
| CRITICAL⚡ | tests/test_error_handler.py | 151 | from linkedin_mcp_server.core.exceptions import ElementNotFoundError | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | linkedin_mcp_server/bootstrap.py | 188 | def _patchright_pkg_version() -> str | None: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 480 | except Exception as exc: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 501 | except Exception as exc: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 519 | except Exception as exc: | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 714 | except Exception: # noqa: BLE001 - a notice failure must not block import | CODE |
| LOW | linkedin_mcp_server/bootstrap.py | 878 | except Exception: # noqa: BLE001 - any import failure -> manual login | CODE |
| LOW | linkedin_mcp_server/error_diagnostics.py | 291 | except Exception: | CODE |
| LOW | linkedin_mcp_server/error_diagnostics.py | 341 | except Exception: | CODE |
| MEDIUM | linkedin_mcp_server/error_diagnostics.py | 288 | def _safe_source_profile_dir(): | CODE |
| LOW | linkedin_mcp_server/greenlet_runtime.py | 102 | except Exception: | CODE |
| LOW | linkedin_mcp_server/server.py | 122 | except Exception: | CODE |
| LOW | linkedin_mcp_server/server.py | 298 | except Exception as e: | CODE |
| LOW | linkedin_mcp_server/daemon_owner.py | 568 | except Exception: | CODE |
| LOW | linkedin_mcp_server/daemon_owner.py | 811 | except Exception: | CODE |
| LOW | linkedin_mcp_server/daemon_proxy.py | 340 | except Exception as exc: | CODE |
| LOW | linkedin_mcp_server/daemon_proxy.py | 479 | except Exception: | CODE |
| LOW | linkedin_mcp_server/daemon_proxy.py | 627 | except Exception as exc: | CODE |
| LOW | linkedin_mcp_server/daemon_proxy.py | 665 | except Exception as exc: | CODE |
| LOW | linkedin_mcp_server/daemon_proxy.py | 752 | except Exception: | CODE |
| LOW | linkedin_mcp_server/daemon_proxy.py | 781 | except Exception: | CODE |
| LOW | linkedin_mcp_server/logging_config.py | 114 | except Exception: | CODE |
| LOW | linkedin_mcp_server/update_check.py | 116 | except Exception: # noqa: BLE001 - never let a version check break a tool call | CODE |
| LOW | linkedin_mcp_server/update_check.py | 192 | except Exception: # noqa: BLE001 - fall back to env / managed detection | CODE |
| MEDIUM | linkedin_mcp_server/update_check.py | 86 | def _read_cache() -> tuple[float, str] | None: | CODE |
| LOW | linkedin_mcp_server/daemon_election.py | 406 | except Exception: | CODE |
| LOW | linkedin_mcp_server/daemon_election.py | 452 | except Exception: | CODE |
| LOW | linkedin_mcp_server/daemon_election.py | 469 | except Exception: | CODE |
| LOW | linkedin_mcp_server/debug_trace.py | 113 | except Exception: | CODE |
| LOW⚡ | linkedin_mcp_server/debug_trace.py | 133 | except Exception as exc: # pragma: no cover - best effort diagnostics | CODE |
| LOW⚡ | linkedin_mcp_server/debug_trace.py | 138 | except Exception as exc: # pragma: no cover - best effort diagnostics | CODE |
| LOW⚡ | linkedin_mcp_server/debug_trace.py | 146 | except Exception: # pragma: no cover - best effort diagnostics | CODE |
| LOW⚡ | linkedin_mcp_server/debug_trace.py | 151 | except Exception: # pragma: no cover - best effort diagnostics | CODE |
| LOW | linkedin_mcp_server/debug_trace.py | 167 | except Exception as exc: # pragma: no cover - best effort diagnostics | CODE |
| MEDIUM | linkedin_mcp_server/debug_trace.py | 110 | def _safe_source_profile_dir() -> Path: | CODE |
| LOW | linkedin_mcp_server/cli_main.py | 264 | except Exception as e: | CODE |
| LOW | linkedin_mcp_server/cli_main.py | 291 | except Exception as e: | CODE |
| LOW | linkedin_mcp_server/cli_main.py | 354 | except Exception: | CODE |
| LOW | linkedin_mcp_server/cli_main.py | 398 | except Exception: | CODE |
| LOW | linkedin_mcp_server/cli_main.py | 411 | except Exception: | CODE |
| LOW | linkedin_mcp_server/cli_main.py | 597 | except Exception as e: | CODE |
| LOW | linkedin_mcp_server/cli_main.py | 621 | except Exception: | CODE |
| LOW | linkedin_mcp_server/cli_main.py | 631 | except Exception as e: | CODE |
| MEDIUM | linkedin_mcp_server/cli_main.py | 251 | def check_session() -> bool: | CODE |
| LOW | linkedin_mcp_server/setup.py | 330 | except Exception as e: | CODE |
| LOW | linkedin_mcp_server/setup.py | 347 | except Exception as e: | CODE |
| LOW⚡ | linkedin_mcp_server/error_handler.py | 59 | except Exception: | CODE |
| LOW | linkedin_mcp_server/sequential_tool_middleware.py | 135 | except Exception: | CODE |
| LOW | linkedin_mcp_server/server_role.py | 199 | except Exception: # noqa: BLE001 - unreadable is not the same as free | CODE |
| LOW | linkedin_mcp_server/dependencies.py | 109 | except Exception as close_exc: | CODE |
| LOW | linkedin_mcp_server/dependencies.py | 178 | except Exception as e: | CODE |
| LOW | linkedin_mcp_server/daemon_auth.py | 167 | except Exception as exc: | CODE |
| LOW | linkedin_mcp_server/daemon_auth.py | 219 | except Exception: # noqa: BLE001 - a marker must not fail on a probe | CODE |
| LOW | linkedin_mcp_server/daemon_auth.py | 295 | except Exception: | CODE |
| LOW | linkedin_mcp_server/daemon_auth.py | 377 | except Exception: # noqa: BLE001 - an unresolvable tool is not a safe one | CODE |
| LOW | linkedin_mcp_server/browser_import/orchestrate.py | 94 | except Exception as exc: # noqa: BLE001 - a single profile must not abort | CODE |
| LOW | linkedin_mcp_server/browser_import/orchestrate.py | 170 | except Exception as exc: # noqa: BLE001 - one bad profile must not abort the run | CODE |
| MEDIUM | linkedin_mcp_server/scraping/extractor.py | 1302 | def _read() -> None: | CODE |
| LOW⚡ | linkedin_mcp_server/scraping/extractor.py | 798 | except Exception: | CODE |
| LOW⚡ | linkedin_mcp_server/scraping/extractor.py | 803 | except Exception: | CODE |
| LOW⚡ | linkedin_mcp_server/scraping/extractor.py | 810 | except Exception: | CODE |
| 113 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | linkedin_mcp_server/bootstrap.py | 641 | return False | COMMENT |
| LOW | linkedin_mcp_server/bootstrap.py | 1121 | # A failure here used to stop the login, and that reasoning has expired. | COMMENT |
| LOW | linkedin_mcp_server/server.py | 181 | # function directly, and a caller that built an OWNER while the process was | COMMENT |
| LOW | linkedin_mcp_server/server.py | 201 | # An inner position would work: `close_browser` does not consult the in-flight | COMMENT |
| LOW | linkedin_mcp_server/server.py | 221 | # built, which loaded that configuration first, and need not for one | COMMENT |
| LOW | linkedin_mcp_server/daemon_owner.py | 81 | READY = "ready" | COMMENT |
| LOW | linkedin_mcp_server/daemon_owner.py | 421 | # descriptor is published nobody can reach this owner, and counting the | COMMENT |
| LOW | linkedin_mcp_server/daemon_owner.py | 501 | # | COMMENT |
| LOW | linkedin_mcp_server/daemon_owner.py | 761 | # how this process logs. | COMMENT |
| LOW | linkedin_mcp_server/hidden_target.py | 161 | # hidden page is simply gone. `context.new_cdp_session` is the obvious call | COMMENT |
| LOW | linkedin_mcp_server/daemon_proxy.py | 101 | #: It does **not** bound a queued call, and no value derived from the tool timeout | COMMENT |
| LOW | linkedin_mcp_server/daemon_proxy.py | 121 | #: listing already in flight against the departing owner can refill the cache | COMMENT |
| LOW | linkedin_mcp_server/daemon_proxy.py | 521 | # that call was bound to. Read together and never separately: a call that | COMMENT |
| LOW | linkedin_mcp_server/daemon_proxy.py | 541 | auth=token, | COMMENT |
| LOW | linkedin_mcp_server/session_state.py | 281 | # anything built on moby writes. | COMMENT |
| LOW | linkedin_mcp_server/daemon_descriptor.py | 61 | from typing import Any | COMMENT |
| LOW | linkedin_mcp_server/daemon_descriptor.py | 81 | #: (:mod:`linkedin_mcp_server.daemon_liveness`) are a control route and call | COMMENT |
| LOW | linkedin_mcp_server/daemon_descriptor.py | 361 | COMMENT | |
| LOW | linkedin_mcp_server/daemon_descriptor.py | 661 | # A URL is printable ASCII. Stated as a rule rather than as a list of | COMMENT |
| LOW | linkedin_mcp_server/daemon_descriptor.py | 701 | f"into a usable address: {self.url!r}" | COMMENT |
| LOW | linkedin_mcp_server/daemon_lock.py | 61 | logger = logging.getLogger(__name__) | COMMENT |
| LOW | linkedin_mcp_server/daemon_lock.py | 301 | # live path sits free for somebody else to take, which is two owners. | COMMENT |
| LOW | linkedin_mcp_server/daemon_lock.py | 321 | # longer there. | COMMENT |
| LOW | linkedin_mcp_server/daemon_election.py | 61 | logger = logging.getLogger(__name__) | COMMENT |
| LOW | linkedin_mcp_server/daemon_election.py | 181 | # out of time is never put here, because the next probe may well reach it: | COMMENT |
| LOW | linkedin_mcp_server/daemon_election.py | 241 | # this re-read normally succeeds at once. The wait is for the other | COMMENT |
| LOW | linkedin_mcp_server/daemon_election.py | 341 | True, | COMMENT |
| LOW | linkedin_mcp_server/daemon_election.py | 641 | # dies during imports still leaves its traceback somewhere. A | COMMENT |
| LOW | linkedin_mcp_server/daemon_election.py | 661 | started = time.monotonic() | COMMENT |
| LOW | linkedin_mcp_server/daemon_election.py | 681 | ) | COMMENT |
| LOW | linkedin_mcp_server/daemon_election.py | 841 | #: Environment variables carrying a secret that the owner has no use for. It | COMMENT |
| LOW | linkedin_mcp_server/daemon_liveness.py | 41 | logger = logging.getLogger(__name__) | COMMENT |
| LOW | linkedin_mcp_server/daemon_liveness.py | 61 | _ID_HEX = 32 | COMMENT |
| LOW | linkedin_mcp_server/cli_main.py | 521 | try: | COMMENT |
| LOW | linkedin_mcp_server/cli_main.py | 561 | # Host and Origin, so those agree and origin validation alone | COMMENT |
| LOW | linkedin_mcp_server/private_state.py | 181 | raise PrivateStateError(f"{path} could not be opened to harden: {exc}") from exc | COMMENT |
| LOW | linkedin_mcp_server/setup.py | 81 | # frontend takes when the shared browser asks it to sign in. A proxy holds no | COMMENT |
| LOW | linkedin_mcp_server/setup.py | 101 | # can be trusted: the profile is held, so nothing can change underneath | COMMENT |
| LOW | linkedin_mcp_server/profile_claim.py | 61 | #: Entries that say nothing about whether a root already belongs to somebody, | COMMENT |
| LOW | linkedin_mcp_server/error_handler.py | 81 | COMMENT | |
| LOW | linkedin_mcp_server/error_handler.py | 101 | # ToolError. Measured through a real tool: a failure wrapped twice arrived | COMMENT |
| LOW | linkedin_mcp_server/server_role.py | 61 | #: login window may be opened is decided far down the stack, in ``bootstrap``, | COMMENT |
| LOW | linkedin_mcp_server/browser_downgrade.py | 61 | #: Anchored to whitespace or the start of the line, which is the part that stops | COMMENT |
| LOW | linkedin_mcp_server/browser_downgrade.py | 81 | #: | COMMENT |
| LOW | linkedin_mcp_server/browser_downgrade.py | 101 | #: Chrome for Testing for most targets but its own Chromium build for Linux | COMMENT |
| LOW | linkedin_mcp_server/browser_downgrade.py | 121 | #: Revision 1200 (patchright 1.57.0) moved macOS *and* Linux x64 to Chrome for | COMMENT |
| LOW | linkedin_mcp_server/browser_downgrade.py | 141 | #: `playwright.download.prss.microsoft.com/dbazure/download/playwright`, then | COMMENT |
| LOW | linkedin_mcp_server/browser_downgrade.py | 161 | #: The other platforms, measured under Docker rather than reasoned about, since | COMMENT |
| LOW | linkedin_mcp_server/browser_downgrade.py | 181 | #: the bundled Chrome for Testing already wrote. Drop the entry and that launch | COMMENT |
| LOW | linkedin_mcp_server/dependencies.py | 81 | which is the safe direction for a default to point. | COMMENT |
| LOW | linkedin_mcp_server/dependencies.py | 101 | # `invalidate_auth_and_trigger_relogin` exactly as a frontend does, so | COMMENT |
| LOW | linkedin_mcp_server/dependencies.py | 121 | # still held. | COMMENT |
| LOW | linkedin_mcp_server/daemon_auth.py | 121 | #: Only forward tolerance is needed, and that asymmetry is deliberate rather than | COMMENT |
| LOW | linkedin_mcp_server/daemon_auth.py | 181 | # it". Two frontends meeting one dead session would otherwise both | COMMENT |
| LOW | linkedin_mcp_server/daemon_auth.py | 301 | COMMENT | |
| LOW | linkedin_mcp_server/daemon_auth.py | 321 | # moved the deadline: an MCP client that gives up on its own call | COMMENT |
| LOW | linkedin_mcp_server/daemon_auth.py | 441 | return | COMMENT |
| LOW | linkedin_mcp_server/browser_launch.py | 21 | # in the HTTP request and the real IPv4 *and* IPv6 in the ICE candidates at the | COMMENT |
| LOW | linkedin_mcp_server/browser_launch.py | 61 | "width": browser.viewport_width, | COMMENT |
| LOW | linkedin_mcp_server/browser_import/discovery.py | 41 | # renames the SERVICE (e.g. Helium account "Helium" but service | COMMENT |
| 49 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | linkedin_mcp_server/bootstrap.py | 3 | CODE | |
| LOW | linkedin_mcp_server/error_diagnostics.py | 3 | CODE | |
| LOW | linkedin_mcp_server/greenlet_runtime.py | 146 | CODE | |
| LOW | linkedin_mcp_server/daemon_config.py | 23 | CODE | |
| LOW | linkedin_mcp_server/server.py | 51 | CODE | |
| LOW | linkedin_mcp_server/daemon_owner.py | 39 | CODE | |
| LOW | linkedin_mcp_server/hidden_target.py | 25 | CODE | |
| LOW | linkedin_mcp_server/hidden_target.py | 38 | CODE | |
| LOW | linkedin_mcp_server/daemon_proxy.py | 36 | CODE | |
| LOW | linkedin_mcp_server/session_state.py | 3 | CODE | |
| LOW | linkedin_mcp_server/daemon_descriptor.py | 45 | CODE | |
| LOW | linkedin_mcp_server/update_check.py | 16 | CODE | |
| LOW | linkedin_mcp_server/daemon_lock.py | 44 | CODE | |
| LOW | linkedin_mcp_server/daemon_election.py | 31 | CODE | |
| LOW | linkedin_mcp_server/debug_trace.py | 3 | CODE | |
| LOW | linkedin_mcp_server/daemon_liveness.py | 28 | CODE | |
| LOW | linkedin_mcp_server/private_state.py | 23 | CODE | |
| LOW | linkedin_mcp_server/windows_acl.py | 23 | CODE | |
| LOW | linkedin_mcp_server/profile_claim.py | 28 | CODE | |
| LOW | linkedin_mcp_server/sequential_tool_middleware.py | 3 | CODE | |
| LOW | linkedin_mcp_server/common_utils.py | 3 | CODE | |
| LOW | linkedin_mcp_server/daemon.py | 36 | CODE | |
| LOW | linkedin_mcp_server/browser_launch.py | 14 | CODE | |
| LOW | linkedin_mcp_server/profile_lease.py | 32 | CODE | |
| LOW | linkedin_mcp_server/debug_utils.py | 3 | CODE | |
| LOW | linkedin_mcp_server/daemon_version.py | 29 | CODE | |
| LOW | linkedin_mcp_server/browser_import/discovery.py | 10 | CODE | |
| LOW | linkedin_mcp_server/browser_import/__init__.py | 10 | CODE | |
| LOW | linkedin_mcp_server/browser_import/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/browser_import/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/browser_import/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/browser_import/__init__.py | 17 | CODE | |
| LOW | linkedin_mcp_server/browser_import/__init__.py | 17 | CODE | |
| LOW | linkedin_mcp_server/browser_import/orchestrate.py | 22 | CODE | |
| LOW | linkedin_mcp_server/browser_import/extract.py | 17 | CODE | |
| LOW | linkedin_mcp_server/scraping/__init__.py | 3 | CODE | |
| LOW | linkedin_mcp_server/scraping/__init__.py | 4 | CODE | |
| LOW | linkedin_mcp_server/scraping/__init__.py | 4 | CODE | |
| LOW | linkedin_mcp_server/scraping/__init__.py | 4 | CODE | |
| LOW | linkedin_mcp_server/scraping/__init__.py | 4 | CODE | |
| LOW | linkedin_mcp_server/scraping/extractor.py | 3 | CODE | |
| LOW | linkedin_mcp_server/scraping/connection.py | 21 | CODE | |
| LOW | linkedin_mcp_server/scraping/link_metadata.py | 3 | CODE | |
| LOW | linkedin_mcp_server/drivers/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/drivers/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/drivers/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/drivers/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/drivers/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/drivers/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/drivers/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/drivers/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/drivers/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/drivers/__init__.py | 16 | CODE | |
| LOW | linkedin_mcp_server/core/__init__.py | 3 | CODE | |
| LOW | linkedin_mcp_server/core/__init__.py | 3 | CODE | |
| LOW | linkedin_mcp_server/core/__init__.py | 3 | CODE | |
| LOW | linkedin_mcp_server/core/__init__.py | 3 | CODE | |
| LOW | linkedin_mcp_server/core/__init__.py | 3 | CODE | |
| LOW | linkedin_mcp_server/core/__init__.py | 10 | CODE | |
| LOW | linkedin_mcp_server/core/__init__.py | 11 | CODE | |
| 40 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | linkedin_mcp_server/scraping/extractor.py | 997 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | linkedin_mcp_server/scraping/extractor.py | 999 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 519 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 521 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 586 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 588 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 678 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 680 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 742 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 744 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 843 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 845 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 905 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 907 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 141 | # --------------------------------------------------------------------------- | STRING |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 143 | # --------------------------------------------------------------------------- | STRING |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 374 | # --------------------------------------------------------------------------- | STRING |
| MEDIUM⚡ | tests/test_browser_import_extract.py | 376 | # --------------------------------------------------------------------------- | STRING |
| MEDIUM | tests/test_browser_import_extract.py | 473 | # --------------------------------------------------------------------------- | STRING |
| MEDIUM | tests/test_browser_import_extract.py | 475 | # --------------------------------------------------------------------------- | STRING |
| MEDIUM⚡ | tests/test_browser_import_discovery.py | 341 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_browser_import_discovery.py | 343 | # --------------------------------------------------------------------------- | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | linkedin_mcp_server/bootstrap.py | 51 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/server.py | 53 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/daemon_owner.py | 77 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/hidden_target.py | 40 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/daemon_proxy.py | 68 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/session_state.py | 28 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/update_check.py | 34 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/daemon_lock.py | 61 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/daemon_election.py | 61 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/daemon_liveness.py | 41 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/cli_main.py | 49 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/private_state.py | 40 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/profile_claim.py | 42 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/authentication.py | 20 | logger = logging.getLogger(__name__) | CODE |
| LOW⚡ | linkedin_mcp_server/error_handler.py | 48 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/sequential_tool_middleware.py | 19 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/server_role.py | 89 | def set_process_role(role: ServerRole) -> None: | CODE |
| LOW | linkedin_mcp_server/browser_downgrade.py | 45 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/dependencies.py | 39 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/daemon.py | 50 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/daemon_auth.py | 67 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/browser_launch.py | 16 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/profile_lease.py | 48 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/daemon_version.py | 36 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/browser_import/discovery.py | 20 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/browser_import/__init__.py | 19 | __all__ = [ | CODE |
| LOW | linkedin_mcp_server/browser_import/orchestrate.py | 59 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/browser_import/extract.py | 45 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/scraping/fields.py | 5 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/scraping/__init__.py | 11 | __all__ = [ | CODE |
| LOW | linkedin_mcp_server/scraping/extractor.py | 48 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/tools/post.py | 24 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/tools/person.py | 23 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/tools/company.py | 25 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/tools/job.py | 18 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/tools/feed.py | 27 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/tools/messaging.py | 21 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/drivers/__init__.py | 29 | __all__ = [ | CODE |
| LOW | linkedin_mcp_server/drivers/browser.py | 60 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/drivers/browser.py | 796 | def _settle_the_profile(*, confirmed: bool) -> None: | CODE |
| LOW | linkedin_mcp_server/drivers/browser.py | 891 | def set_headless(headless: bool) -> None: | CODE |
| LOW | linkedin_mcp_server/core/auth.py | 12 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/core/__init__.py | 33 | __all__ = [ | CODE |
| LOW | linkedin_mcp_server/core/browser.py | 37 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/core/utils.py | 10 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/core/proxy_errors.py | 17 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/config/loaders.py | 22 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/config/__init__.py | 13 | logger = logging.getLogger(__name__) | CODE |
| LOW | linkedin_mcp_server/config/__init__.py | 28 | def set_config(config: AppConfig) -> None: | CODE |
| LOW | linkedin_mcp_server/config/__init__.py | 54 | __all__ = [ | CODE |
| LOW | linkedin_mcp_server/config/schema.py | 16 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/test_bootstrap.py | 326 | def _set_headless(monkeypatch, headless: bool) -> None: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/conftest.py | 167 | (isolate_profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW⚡ | tests/test_cli_main.py | 417 | (profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW⚡ | tests/test_cli_main.py | 423 | (runtime_profile / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_cli_main.py | 307 | (profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_cli_main.py | 372 | (profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_profile_lease_integration.py | 911 | (profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_profile_lease_integration.py | 1128 | (profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_profile_lease_integration.py | 1233 | (isolate_profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_profile_lease_integration.py | 1283 | (isolate_profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_profile_lease_integration.py | 1345 | (isolate_profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_profile_lease_integration.py | 1386 | (other / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_profile_lease_integration.py | 1419 | (profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_browser_driver.py | 67 | (profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_browser_driver.py | 97 | (profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW⚡ | tests/test_scraping.py | 3041 | return_value=extracted("Jane Doe"), | CODE |
| LOW⚡ | tests/test_scraping.py | 3053 | return_value=extracted("Jane Doe"), | CODE |
| LOW⚡ | tests/test_scraping.py | 3065 | return_value=extracted("Jane Doe"), | CODE |
| LOW⚡ | tests/test_scraping.py | 3094 | return_value=extracted("Jane Doe"), | CODE |
| LOW⚡ | tests/test_scraping.py | 3106 | return_value=extracted("Jane Doe"), | CODE |
| LOW⚡ | tests/test_bootstrap.py | 213 | (profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_bootstrap.py | 2069 | (profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_bootstrap.py | 2179 | (profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_bootstrap.py | 2350 | (isolate_profile_dir / "Default" / "Cookies").write_text("placeholder") | CODE |
| LOW | tests/test_tools.py | 73 | "main_profile": "John Doe", | CODE |
| LOW | tests/test_tools.py | 106 | "sections": {"main_profile": "John Doe"}, | CODE |
| LOW | tests/test_tools.py | 126 | "sections": {"main_profile": "John Doe"}, | CODE |
| LOW | tests/test_tools.py | 166 | "sections": {"main_profile": "John Doe"}, | CODE |
| LOW | tests/test_tools.py | 893 | "sections": {"main_profile": "John Doe", "experience": "Work history"}, | CODE |
| LOW | tests/test_tools.py | 914 | "sections": {"main_profile": "John Doe"}, | CODE |
| LOW | tests/test_tools.py | 933 | "sections": {"main_profile": "John Doe"}, | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | linkedin_mcp_server/setup.py | 43 | Open browser for manual LinkedIn login with persistent profile. Opens a non-headless browser, navigates to Lin | STRING |
| HIGH | linkedin_mcp_server/tools/person.py | 45 | Get a specific person's LinkedIn profile. Args: linkedin_username: LinkedIn username (e.g. | STRING |
| HIGH | linkedin_mcp_server/tools/person.py | 322 | Get the authenticated user's own LinkedIn profile. Navigates to /in/me/ and resolves the redirect to o | STRING |
| HIGH | linkedin_mcp_server/tools/company.py | 46 | Get a specific company's LinkedIn profile. Args: company_name: LinkedIn company name (e.g. | STRING |
| HIGH | linkedin_mcp_server/drivers/browser.py | 533 | Get existing browser or create and initialize a new one. Uses a singleton pattern to reuse the browser across | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | linkedin_mcp_server/server.py | 88 | CODE | |
| LOW | linkedin_mcp_server/hidden_target.py | 112 | CODE | |
| LOW | linkedin_mcp_server/session_state.py | 1013 | CODE | |
| LOW | linkedin_mcp_server/daemon_descriptor.py | 326 | CODE | |
| LOW | linkedin_mcp_server/cli_main.py | 426 | CODE | |
| LOW | linkedin_mcp_server/private_state.py | 316 | CODE | |
| LOW | linkedin_mcp_server/setup.py | 153 | CODE | |
| LOW | linkedin_mcp_server/error_handler.py | 68 | CODE | |
| LOW | linkedin_mcp_server/profile_lease.py | 283 | CODE | |
| LOW | linkedin_mcp_server/browser_import/discovery.py | 210 | CODE | |
| LOW | linkedin_mcp_server/browser_import/orchestrate.py | 272 | CODE | |
| LOW | linkedin_mcp_server/scraping/extractor.py | 1330 | CODE | |
| LOW | linkedin_mcp_server/scraping/extractor.py | 1497 | CODE | |
| LOW | linkedin_mcp_server/scraping/extractor.py | 1732 | CODE | |
| LOW | linkedin_mcp_server/scraping/extractor.py | 1940 | CODE | |
| LOW | linkedin_mcp_server/scraping/extractor.py | 2895 | CODE | |
| LOW | linkedin_mcp_server/scraping/extractor.py | 3227 | CODE | |
| LOW | linkedin_mcp_server/scraping/extractor.py | 3488 | CODE | |
| LOW | linkedin_mcp_server/tools/company.py | 28 | CODE | |
| LOW | linkedin_mcp_server/tools/company.py | 108 | CODE | |
| LOW | linkedin_mcp_server/tools/feed.py | 30 | CODE | |
| LOW | linkedin_mcp_server/tools/feed.py | 42 | CODE | |
| LOW | tests/test_browser_identity.py | 287 | CODE | |
| LOW | tests/test_browser_identity.py | 344 | CODE | |
| LOW | tests/test_profile_lease_integration.py | 390 | CODE | |
| LOW | tests/test_manifest.py | 59 | CODE | |
| LOW | tests/test_manifest.py | 122 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | linkedin_mcp_server/core/auth.py | 47 | # Step 1: Fail-fast on auth blockers | COMMENT |
| LOW⚡ | linkedin_mcp_server/core/auth.py | 51 | # Step 2: Selector check (PRIMARY) | COMMENT |
| LOW⚡ | linkedin_mcp_server/core/auth.py | 60 | # Step 3: URL fallback | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | linkedin_mcp_server/core/auth.py | 47 | # Step 1: Fail-fast on auth blockers | COMMENT |
| LOW⚡ | linkedin_mcp_server/core/auth.py | 51 | # Step 2: Selector check (PRIMARY) | COMMENT |
| LOW⚡ | linkedin_mcp_server/core/auth.py | 60 | # Step 3: URL fallback | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | linkedin_mcp_server/logging_config.py | 67 | # Create a copy of the record to avoid modifying the original | COMMENT |
| MEDIUM | tests/conftest.py | 163 | # Create a marker file so profile_exists() returns True | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | linkedin_mcp_server/bootstrap.py | 778 | # session (orchestrate.py:254). The "no live session" and "could not | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | linkedin_mcp_server/scraping/extractor.py | 3227 | CODE | |
| LOW | linkedin_mcp_server/scraping/extractor.py | 4400 | CODE | |
| LOW | linkedin_mcp_server/tools/job.py | 80 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/test_daemon_proxy.py | 105 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | .github/workflows/release.yml | 48 | # Check if version actually changed | COMMENT |