Skip to content

luisra51/mcp-linkedin-ads

Repository files navigation

LinkedIn Ads MCP server

A Model Context Protocol (MCP) server for the LinkedIn Marketing API.

This server provides read and write access to LinkedIn Ads resources with guardrails.

Requirements

  • Go 1.25+
  • LinkedIn Advertising API approval
  • A LinkedIn OAuth access token with appropriate scopes

Prerequisites

LinkedIn Advertising API Access (Required)

LinkedIn requires approval before you can use the Advertising API. This is a one-time process:

  1. Go to LinkedIn Developer Portal and create an app (or select an existing one)
  2. In the Settings tab, associate a LinkedIn Company Page
  3. Verify the company — send the verification URL to a Page Admin to approve
  4. In the Products tab, click Request access on Advertising API
  5. Fill out the request form with your business justification
  6. Wait for approval (typically 20 minuts after fill the form)

Without this approval, OAuth will fail with invalid_scope_error.

OAuth Scopes

Once approved, the following scopes are available:

Scope Access Required
r_ads Read ad accounts and campaigns Yes
r_ads_reporting Read analytics and reports Yes
rw_ads Create and manage campaigns For write operations
r_organization_social Read organization posts For creative content

Features

Read-only tools (default):

  • Ad accounts list and details
  • Campaigns and campaign groups list
  • Creatives list
  • Campaign, creative, and account analytics
  • Demographic breakdowns
  • Conversion tracking rules

Write tools (opt-in):

  • Create, update, and delete campaign groups
  • Create, update, and delete campaigns
  • Create creatives
  • Update creative status

Installation

Claude Code (stdio)

go build -o mcp-linkedin-ads ./cmd/mcp-linkedin-ads

claude mcp add linkedin-ads \
  --env LINKEDIN_ACCESS_TOKEN=your_token \
  -- ./mcp-linkedin-ads

Claude Desktop

{
  "mcpServers": {
    "linkedin-ads": {
      "command": "/path/to/mcp-linkedin-ads",
      "env": {
        "LINKEDIN_ACCESS_TOKEN": "your_token"
      }
    }
  }
}

Docker (HTTP transport)

docker build -t mcp-linkedin-ads .

docker run -d -p 8001:8001 \
  -e LINKEDIN_ACCESS_TOKEN=your_token \
  mcp-linkedin-ads -t streamable-http --address 0.0.0.0:8001

OAuth Discovery (for MCP clients that support it)

The server exposes .well-known endpoints so OAuth-capable clients can handle authentication automatically:

  • GET /.well-known/oauth-protected-resource
  • GET /.well-known/oauth-authorization-server

MCP clients like Ironclaw can use these to run the OAuth flow:

ironclaw mcp add linkedin-ads http://localhost:8001/mcp \
  --client-id YOUR_CLIENT_ID \
  --scopes "r_ads,r_ads_reporting"

ironclaw mcp auth linkedin-ads

Environment Variables

Variable Required Description
LINKEDIN_ACCESS_TOKEN Yes* OAuth2 Bearer token
LINKEDIN_API_BASE No API base URL (default: https://api.linkedin.com)
LINKEDIN_ALLOW_WRITE No Enable write operations (default: false)
LINKEDIN_ALLOWED_TOOLS No Comma-separated tool allowlist
LINKEDIN_TIMEOUT_MS No Request timeout in ms (default: 30000)
LINKEDIN_DEBUG No Enable debug behavior (default: false)
LINKEDIN_RATE_LIMIT_DISABLE No Disable built-in rate limiting (default: false)
LINKEDIN_MCP_URL No Server URL for .well-known responses

* Not required if the MCP client injects the token via the Authorization: Bearer header.

Optional per-request headers:

  • Authorization: Bearer <token>
  • X-LinkedIn-URL

Rate Limiting

By default the client enforces conservative LinkedIn request limits:

  • 10 requests/second burst
  • 100 requests/minute

Disable with LINKEDIN_RATE_LIMIT_DISABLE=true.

Available Tools (22)

Read Operations (14)

Tool Description
linkedin.accounts.list List all accessible ad accounts
linkedin.accounts.get Get details for a specific ad account
linkedin.campaigns.list List campaigns with pagination
linkedin.campaign_groups.list List campaign groups
linkedin.creatives.list List creatives with pagination
linkedin.analytics.campaign_performance Campaign-level metrics (impressions, clicks, CTR, CPC, CPM, etc.)
linkedin.analytics.creative_performance Creative-level metrics with engagement and video stats
linkedin.analytics.account_performance Account-level aggregated metrics
linkedin.demographics.by_function Breakdown by job function
linkedin.demographics.by_seniority Breakdown by seniority level
linkedin.demographics.by_industry Breakdown by industry
linkedin.demographics.by_company_size Breakdown by company size
linkedin.demographics.by_country Breakdown by country
linkedin.conversions.list List conversion tracking rules

Write Operations (8) — requires LINKEDIN_ALLOW_WRITE=true

Tool Description
linkedin.campaign_groups.create Create a campaign group
linkedin.campaign_groups.update Update group name or status
linkedin.campaign_groups.delete Delete (DRAFT) or archive a group
linkedin.campaigns.create Create a campaign
linkedin.campaigns.update Update campaign name, status, or budget
linkedin.campaigns.delete Delete (DRAFT) or archive a campaign
linkedin.creatives.create Create a creative from a content reference
linkedin.creatives.update_status Activate, pause, or archive a creative

Calculated Metrics

Analytics tools automatically calculate:

  • CTR — Click-through rate (%)
  • CPC — Cost per click
  • CPM — Cost per 1,000 impressions
  • Engagement Rate — Engagements / Impressions (%)
  • Conversion Rate — Conversions / Clicks (%)
  • Cost per Conversion — Spend / Conversions

Transport Options

Flag Transport Use Case
-t stdio Standard I/O (default) Claude Code, Claude Desktop, Codex
-t sse Server-Sent Events Legacy HTTP clients
-t streamable-http Streamable HTTP Ironclaw, modern MCP clients
# stdio (default)
./mcp-linkedin-ads

# HTTP
./mcp-linkedin-ads -t streamable-http --address 0.0.0.0:8001

# SSE
./mcp-linkedin-ads -t sse --address 0.0.0.0:8001 --base-path /

Development

Start the dev container:

task dev:up

Run tests inside the container:

task dev:exec SV=mcp-linkedin-ads-dev CMD='go test ./...'

Build and test locally:

go build ./...
go test ./...
go build -o mcp-linkedin-ads ./cmd/mcp-linkedin-ads

Notes

  • Write tools are disabled unless LINKEDIN_ALLOW_WRITE=true.
  • List endpoints expose pagination via start and count, capped at 100.
  • Analytics and demographics require valid date ranges in YYYY-MM-DD format.

License

MIT

About

MCP server for the LinkedIn Marketing API

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors