LinkedIn Evidence MCP

LinkedIn Evidence MCP

A local-first LinkedIn workspace that turns your own documents, CVs, repositories, and exports into a verifiable claim ledger and evidence-backed canonical profile, enabling evidence import, claim verification, profile patching, post drafting, content planning, analytics, and publication approvals through MCP tools — all stored locally in SQLite with an optional human-review dashboard.

Category
Visit Server

README

LinkedIn Evidence MCP

An independent, community-built tool. Not affiliated with, endorsed by, or sponsored by LinkedIn Corporation or Microsoft. "LinkedIn" is a trademark of LinkedIn Corporation, used here only to describe the service this software interoperates with.

A local-first LinkedIn workspace with one shared engine and two synchronized ways to use it:

  • the stdio MCP server, which is the primary workflow engine for evidence, profile, drafting, analytics, and maintenance;
  • an optional loopback dashboard, which is the visual support and human-review surface over the same tools and data.

The application keeps its own SQLite database and artifact store on this computer. It does not contain an LLM, a hosted service, a scheduler, scraping, browser automation, cookie reuse, or automated engagement.

Nothing here refreshes on a timer. LinkedIn data is pulled only when you or an agent invoke a tool that does it. That is a product decision about predictability, not a restriction imposed by LinkedIn's terms — see reading the latest LinkedIn profile.

What it is for

The app turns evidence you control—CVs, documents, repositories, LinkedIn exports, and manually imported history—into:

  • a verified claim ledger;
  • an evidence-backed canonical profile;
  • exact profile change patches for manual copy/paste;
  • LinkedIn post drafts with deterministic validation;
  • content pillars, opportunities, and a planning calendar;
  • publication approvals and an append-only audit history;
  • local backups, exports, and retention controls.

External LinkedIn features are optional. They remain unavailable until the corresponding developer-app credential is stored, verified against LinkedIn, and explicitly enabled where required. The rest of the product works without those credentials.

Requirements

  • Windows 10 or later, Linux, or macOS. All three are supported and all three run the full test suite on every push.
  • Node.js 24 or later (the database uses the built-in node:sqlite)
  • npm

Evidence import accepts each platform's own absolute-path shape: drive-letter paths on Windows, /-rooted paths on Linux and macOS. The rules genuinely differ — Windows also refuses UNC paths, alternate data streams and reserved device names, while the POSIX rules refuse embedded NUL bytes and the ambiguous // root — because the dangerous shapes differ, not because one platform is trusted more.

The credential vault differs too, and the differences are worth knowing before you rely on it. All three give the same practical guarantee — a data home copied to another machine or another account cannot be opened — but they are not equally strong:

Platform How the master key is sealed
macOS A random key in the login Keychain, held by the OS behind an access-control list strongest
Windows DPAPI, bound to your Windows account
Linux Derived from the host machine id and your user id, never written down weakest — /etc/machine-id is world-readable, so any local process can derive the same key

None of them defends against software running as you, which SECURITY.md has always listed as out of scope. The ranking matters only if a local attacker is in your threat model; if so, prefer macOS or Windows, or do not store LinkedIn credentials at all — everything else works without them.

The interactive setup assistant is Windows-only, because it is PowerShell. On Linux and macOS you configure your MCP client by hand, which is one JSON block — see MCP server setup. npm run setup:mcp prints exactly that block, with the right data home for your platform, rather than failing.

The optional LinkedIn read lane has a second, separate limit: LinkedIn issues Member Data Portability tokens only to members located in the European Economic Area or Switzerland. Everything that does not touch LinkedIn works regardless.

Quick start

From the repository root:

npm run setup:mcp

On Windows this runs the interactive assistant described below. On Linux and macOS the assistant does not apply — it is PowerShell and writes Windows client paths — so npm run setup:mcp instead prints the one JSON block you add to your MCP client by hand, with the right data home for your platform, and the rest of this section (the PowerShell commands) is Windows-only. Per-client examples are in MCP server setup; the short version is Use the MCP without the dashboard below, which is identical on every platform.

See what it would do first (Windows):

powershell -NoProfile -ExecutionPolicy Bypass -File .\setup-mcp.ps1 -All -NonInteractive -DryRun

Windows refuses to run an unsigned .ps1 under its default Restricted execution policy, so a bare .\setup-mcp.ps1 fails before it does anything. -ExecutionPolicy Bypass applies to that one invocation and changes nothing on the machine — which is also exactly what npm run setup:mcp does. Read the script first if you would rather not take that on trust; -DryRun prints every file it would touch without opening any of them for writing.

The assistant edits configuration files that belong to other applications, so it is worth knowing which before you let it run. Depending on the clients you select it can write to ~/.codex/config.toml, ~/.claude.json, %APPDATA%\Claude\claude_desktop_config.json, %APPDATA%\Code\User\mcp.json, ~/.copilot/mcp-config.json, ~/.cursor/mcp.json, and ~/.gemini/config/mcp_config.json. Unless you pass -NoPersistUserEnvironment it also saves LINKEDIN_MCP_HOME as a user-scope environment variable.

Every file it touches is backed up with a timestamped copy first, only the linkedin entry is replaced, a file that is not strict JSON is refused rather than rewritten, and a failure restores the original.

The interactive assistant checks Node.js, installs dependencies when needed, builds the MCP server, asks which AI clients to configure, and points every selection at one shared data home. It supports Codex, Claude Code, Claude Desktop, VS Code/Copilot Chat, GitHub Copilot CLI, Cursor, and Google Antigravity. Existing JSON configurations are merged and backed up; only the linkedin MCP entry is replaced.

Restart the configured clients, then choose either or both surfaces:

# MCP server: normally started automatically by your AI client
npm run mcp:start

# Optional human review dashboard
npm run dashboard

mcp:start speaks JSON-RPC over stdin/stdout and therefore appears to wait when run in an ordinary terminal. That is expected. Configure an MCP client to launch it instead; see MCP server setup.

The dashboard prints a single-use URL for http://127.0.0.1:4780. See dashboard usage.

For repeatable or unattended setup:

powershell -NoProfile -ExecutionPolicy Bypass -File .\setup-mcp.ps1 -Clients Codex,Cursor,VSCode -NonInteractive
powershell -NoProfile -ExecutionPolicy Bypass -File .\setup-mcp.ps1 -All -NonInteractive

Use -DataHome "C:\absolute\path" to choose a different shared home. The assistant saves that absolute path as the current user's LINKEDIN_MCP_HOME; open a new terminal before starting the dashboard so it inherits a newly saved custom value. Pass -NoPersistUserEnvironment if you only want the selected client entries changed. The assistant never asks for or writes LinkedIn credentials.

Shared state between MCP and dashboard

The dashboard and every configured MCP process open the same local application home. You can work in the dashboard, close it, continue through an AI agent, and return later without importing or reconciling anything manually.

All paths below are under the data home (see Data location).

Shared state Where it lives
Evidence, claims, profile state, decisions, drafts, revisions, approvals, publication history, audit events, settings, and progress data/linkedin.sqlite3
Imported working copies and generated artifacts artifacts/
Encrypted LinkedIn credentials Ciphertext in SQLite plus the sealed master key in secrets/ — DPAPI on Windows, Keychain-sealed on macOS, machine-derived on Linux
Backups backups/

SQLite WAL mode and bounded write retries allow the dashboard and MCP clients to run at the same time. The dashboard refreshes the current screen when it regains focus and periodically while visible, so agent-side changes appear without restarting it.

This is local synchronization on one user account, not cloud or multi-machine synchronization. Secrets remain usable by both processes but are never copied into AI-client configuration, returned to a model, exported, logged, or included in backups.

Use the MCP without the dashboard

The dashboard and MCP server are separate processes. You do not need to start the dashboard before connecting Codex, Claude, Copilot, Cursor, Antigravity, VS Code, or another stdio MCP host.

After building, configure the client to launch the compiled entrypoint with an absolute path (backslashes on Windows, / on Linux and macOS):

node <absolute-path-to-repo>/linkedin-mcp-server/dist/index.js

To add and import the first evidence source from a human-operated terminal — the path is an example, use your own absolute path in the shape your platform accepts:

npm run evidence:add -- "C:\path\to\cv.pdf" document personal_doc "Current CV"
# Linux / macOS:  npm run evidence:add -- "/home/you/cv.pdf" document personal_doc "Current CV"

That command explicitly registers, enables, and imports the source without opening the dashboard. Source kinds are repo, document, folder, linkedin_export, and manual; trust levels are personal_doc, own_repo, and local_clone_reference.

You can then ask the connected agent to:

Use the LinkedIn MCP capability-status tool, then list my evidence sources and candidate claims.

The MCP drives the normal workflow. The dashboard includes purpose-built review screens plus System → All MCP tools, which exposes the exact same validated tool registry—there is no dashboard-only copy of the business logic. Secret entry is the only operation intentionally unavailable through chat. Other consequential operations require an explicit confirmation bound to the action:

Action Dashboard-free option
Register, enable, and import evidence MCP (ENABLE <source_id> is required to enable), npm run evidence:add -- ..., or the dashboard/CLI
Change non-secret settings linkedin_settings_set MCP tool
Store LinkedIn access tokens `npm run control -- lane configure read
Grant, decline, or revise a publication approval Tell the connected agent your decision and confirm its bound command for linkedin_approval_decide, or use the dashboard/control CLI
Enable real publishing linkedin_feature_control, dashboard Features, or npm run control -- feature enable live_publishing --confirm, after write-lane verification
Publish to the account linkedin_publish_execute with PUBLISH <approval_id> after grant; text posts only in this version
Delete LinkedIn portability data only linkedin_purge_run mode purge_dma, or npm run control -- purge dma --confirm "DELETE LINKEDIN PORTABILITY DATA"; prune_dma / --before <ISO> drops older history and keeps the current profile
Permanently purge all local data Confirmed linkedin_purge_run, dashboard, or npm run control -- purge all --confirm "DELETE ALL LOCAL DATA"

Run npm run control with no arguments for an interactive menu. The CLI is also the dashboard-free secret-entry surface; access tokens are masked and never enter MCP payloads.

Shared feature controls

Nine feature groups are stored in the shared SQLite database and enforced by both MCP handlers and dashboard routes: evidence, profile, content, publication_workflow, analytics, linkedin_sync, maintenance, configuration, and live_publishing. The first eight default to enabled. Only live_publishing defaults to disabled.

List descriptions and current values with linkedin_feature_control, System → Features, or:

npm run control -- feature list
npm run control -- feature disable analytics --confirm
npm run control -- feature enable analytics --confirm

Feature policy is separate from LinkedIn credential/API readiness. Enabling live_publishing therefore still requires a verified write lane, and every real post still requires a granted revision-bound approval plus the exact publish command.

Evidence workflow and decisions

The intended flow is MCP-first:

  1. Register an evidence path with MCP, then explicitly confirm ENABLE <source_id> through the agent, dashboard, or control CLI.
  2. Let the agent import it, verify stored-byte integrity, inspect the extracted artifacts, and propose narrow claims with citations.
  3. Review the exact statements. Non-conflicting claims become verified only after explicit human confirmation.
  4. Escalate conflicts, ambiguous wording, and overstatements for human review. Resolve them through MCP conversation or the dashboard; both call the same claim and conflict services.

Claim statements are immutable history. “Modify” creates corrected wording as a new claim, then rejects or merges the old claim. This keeps previous decisions auditable instead of silently rewriting evidence.

Data location

The default home is each platform's own convention:

Platform Default home
Windows %LOCALAPPDATA%\linkedin-mcp
macOS ~/Library/Application Support/linkedin-mcp (or $XDG_DATA_HOME/linkedin-mcp if set)
Linux $XDG_DATA_HOME/linkedin-mcp, otherwise ~/.local/share/linkedin-mcp

Set LINKEDIN_MCP_HOME to an absolute directory to use a different home or an isolated test corpus; it overrides the default on every platform. Relative paths are rejected because different client working directories could otherwise create separate databases — and on Windows a drive-relative path like \linkedin-data is rejected for the same reason, since it resolves against whichever drive a process is on. The setup assistant configures the same absolute value everywhere.

Do not place the live home in OneDrive, Dropbox, Google Drive, iCloud Drive, or another synchronization folder. SQLite uses a live WAL database, which should not be copied while open. Use the built-in backup command instead.

Repository map

Path Responsibility
linkedin-mcp-server/ Primary engine: 44 MCP tools, 5 resources, 5 workflow prompts, stdio transport
linkedin-dashboard/ Optional loopback visual support, human review, and exact MCP-tool console
packages/domain/ Evidence, profile, drafts, approvals, publication, audit, retention
packages/db/ SQLite driver, migrations, optimistic concurrency, artifact storage
packages/importers/ Path-safe ZIP, CSV, PDF, DOCX, repository scanning, and redaction
packages/linkedin/ Fail-closed LinkedIn OIDC, DMA, and publishing adapters
packages/shared/ Canonical JSON, identifiers, and error contracts
scripts/ Human-operated onboarding, maintenance, and evaluation commands

Safety model

  • Only verified claims can back public profile text or drafts.
  • Imported content is always treated as untrusted data, never as instructions.
  • MCP can grant, reject, or revise a publication request only after the user explicitly confirms the exact approval command; grants are bound to the revision hash.
  • Approval is bound to one exact draft revision and consumed before publishing.
  • An uncertain network outcome becomes ambiguous; it is never retried automatically.
  • The audit log is hash-chained; a broken chain blocks approvals and publication.
  • Imports copy content into the artifact store and never modify the originals.
  • Secrets are excluded from MCP payloads, logs, exports, and backups.

Development and verification

npm ci
npm run typecheck
npm run build
npm test
npm run inspect:list
npm run test:visual

Build before test. The protocol-cleanliness suite drives the compiled stdio server, so npm test needs linkedin-mcp-server/dist/index.js to exist. Running the steps in the order above is enough; there is no separate setup.

inspect:list starts the compiled stdio server through MCP Inspector and requests its tool catalog. Visual tests require Playwright browser installation.

For optional LinkedIn developer-app configuration, see docs/linkedin-app-setup.md.

Documentation

Document What it covers
docs/architecture.md Two surfaces, one engine; the seams that are not obvious
docs/compatibility.md Supported platforms, runtime, MCP clients, and the known verification gap
docs/known-limitations.md What this does not do, and which limits are deliberate
docs/privacy-and-local-data.md What is stored, what leaves the machine, how to delete it
docs/threat-model.md Assets, trust boundaries, and where protection stops
docs/releases.md Versioning, upgrading, and why downgrade is unsupported
docs/linkedin-app-setup.md Creating the two LinkedIn developer apps
docs/dashboard-design.md Dashboard design system
docs/dashboard-manual-checks.md Manual accessibility and viewport checklist
SECURITY.md Reporting a vulnerability; non-goals
CONTRIBUTING.md Getting a green build; the rules that are not negotiable
SUPPORT.md Where to ask, and what is out of scope

License

MIT — see LICENSE. Third-party dependency licenses are listed in THIRD-PARTY-NOTICES.md; trademark and affiliation wording lives in NOTICE.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured