Skip to main content
Glama
get-mcp-ads

LinkedIn Ads MCP Server

LinkedIn Ads MCP server

Bring your LinkedIn Ads accounts into your MCP client.

Read campaign structure, performance and professional demographics, and prepare draft campaigns and ads for explicitly selected accounts.

Release CI License: Apache 2.0 Node

Watch the film · What's new · Install · Tool reference · Try hosted getmcpads

Watch the getmcpads film: every ad account in one conversation with your AI assistant

Play the 45-second film

The film shows hosted getmcpads with sample data. Its MCP Apps, from creative galleries and alerts to Google Sheets exports and bulk launches, belong to the hosted product. This repository provides the standalone native API tools.

18 read tools · 15 write tools, disabled by default.

Run locally with your own LinkedIn app credentials and a client that supports stdio MCP, such as Claude Desktop, Claude Code or Cursor. Your requests go directly to the LinkedIn Marketing API. For managed connections, including supported ChatGPT setups, use the hosted option.

What's new

v1.0.1: Zod 4 security update · October 26, 2026

  • Update zod to 4.6.7. Every Zod release before 4.6.6 is covered by the high-severity advisory GHSA-mrhx-c7xc-m3w5: validating an oversized constrained collection can exhaust memory, and no Zod 3 release carries the fix. npm audit --omit=dev reports no vulnerability again.

  • Keep the Zod 3 validation behaviour. A parameter default is still validated and completed before use, so an omitted object must still supply its required fields.

  • Tool names, parameters and descriptions published over MCP are unchanged. server-card.json is regenerated with Zod 4's JSON Schema output, which spells some constraints differently.

Earlier releases

Version

Date

Highlights

1.0.0

October 23, 2026

First standalone release

Full changelog · All releases

Source synchronization: SOURCE_SYNC.md.

Upgrade notes

Requires Node.js 22.23.4, 24.22.1, 26.12.1 or a newer release. These carry the October 2026 security fixes, and the server prints a warning on stderr when it runs on an older one. CI covers Node 22, 24 and 26.

This is the first release. Hosted creative galleries, campaign launches and MCP Apps UI are outside it.

Related MCP server: LinkedIn Ads MCP Toolkit

Install this release

This is a GitHub source release. npm and MCP Registry versions are published separately. The commands below select this exact version; unpinned npx examples later in this document select the version currently available on npm.

git clone --branch v1.0.1 --depth 1 https://github.com/get-mcp-ads/linkedin-ads-mcp-server.git
cd linkedin-ads-mcp-server
npm ci
npm run build

Configure your MCP client to run node with the absolute path to dist/cli.js and the variables documented below. Once the package is on npm, the client can run npx -y @getmcpads/linkedin-ads-mcp-server instead, which starts the linkedin-ads-mcp binary.

{
  "mcpServers": {
    "linkedin-ads": {
      "command": "node",
      "args": ["/absolute/path/to/linkedin-ads-mcp-server/dist/cli.js"],
      "env": {
        "LINKEDIN_ADS_ACCESS_TOKEN": "your-member-access-token",
        "LINKEDIN_ADS_ACCOUNT_IDS": "512345678"
      }
    }
  }
}

npm run doctor reports which variables are set, never their values, and checks the Node.js release.

Prefer a managed connection? Use LinkedIn Ads with hosted getmcpads. Connect your account, select the data your assistant may access and use the hosted MCP connection. See the site for current features and plans.

Configuration

Provide these environment variables through the client's secret configuration:

Variable

Purpose

LINKEDIN_ADS_ACCESS_TOKEN

Member access token from your own LinkedIn app. Required unless the three refresh variables are set.

LINKEDIN_ADS_REFRESH_TOKEN

Programmatic refresh token, for apps LinkedIn approved for them. The access token is then renewed in memory.

LINKEDIN_ADS_CLIENT_ID

Client ID of your app. Used with the refresh token.

LINKEDIN_ADS_CLIENT_SECRET

Client secret of your app. Used with the refresh token.

LINKEDIN_ADS_ACCOUNT_IDS

Required. 1 to 100 comma-separated numeric ad account IDs. Every other account is refused before any request, reads included.

LINKEDIN_ADS_SCOPES

Optional. Scopes actually granted to the token. When set, writes refuse to run without rw_ads. Setting it grants nothing.

LINKEDIN_ADS_ENABLE_WRITES

Defaults to false. Only the exact value true exposes the write tools.

LINKEDIN_ADS_API_VERSION

LinkedIn-Version header as YYYYMM. Defaults to 202608, the version the hosted gateway runs.

LINKEDIN_ADS_LOG_LEVEL

debug, info, warn or error. Logs go to stderr. Defaults to info.

The server validates the configuration at startup and names the variable to fix. It runs no OAuth browser flow and writes nothing to disk: a token renewed through the refresh token stays in memory until the process ends.

What your LinkedIn app needs

LinkedIn Marketing API access is granted per application, so this server runs with an app you own. LinkedIn's quick start describes the steps:

  1. Create a LinkedIn Page, then a developer application in the LinkedIn Developer Portal.

  2. Request the Advertising API product from the app's Products tab and complete the access form. LinkedIn reviews each request.

  3. Every application starts on the Development tier: reads have no account limit, and edits are limited to five ad accounts you administer. On this tier, add each ad account ID under Products, View Ad Accounts. The Standard tier removes the edit limit and is requested through the Developer Support Portal. See access tiers.

  4. Generate a member access token with the Token Generator, or your own authorization code flow, with the scopes below. Access tokens last 60 days. Apps approved for programmatic refresh tokens receive a refresh token valid for a year, which this server can use.

Scopes used by the tools of this server:

Scope

Needed for

r_ads

Account, campaign group, campaign, creative and media library reads, and targeting lookup. rw_ads also allows these reads.

r_ads_reporting

linkedin_get_insights, linkedin_run_statistics_report, linkedin_get_demographics, linkedin_get_revenue_attribution and the reporting probe of linkedin_health_check.

r_organization_social

linkedin_list_ad_creatives, which reads the sponsored post behind each sponsored content ad.

rw_ads

Every write tool.

w_organization_social

linkedin_create_media_ad, which creates the dark post sponsored by the ad, authored by the Company Page of the ad account.

LinkedIn roles still decide what the token can do. A VIEWER on an ad account can only read, even with rw_ads; writes need ACCOUNT_BILLING_ADMIN, ACCOUNT_MANAGER, CAMPAIGN_MANAGER or CREATIVE_MANAGER (account roles). Media uploads and sponsored image or video ads belong to the Company Page referenced by the ad account, which needs an administrator or sponsored content poster role on that Page. linkedin_health_check lists the configured accounts the token reaches and the ones it does not.

Safety and coverage

Writes preview by default. Review the exact account, target and parameters before repeating the call with confirm: true. Campaign groups, campaigns and ads are created as DRAFT, and sponsored posts use feedDistribution: NONE, so nothing reaches the organic feed. New campaigns keep audience expansion and the LinkedIn Audience Network off. No tool activates delivery: activation, where spend starts, happens in Campaign Manager. A preview flags an edit of budget, bid, schedule or targeting, which can change what an already running campaign spends. Do not retry a write automatically when its result is uncertain. A failed write reports verify_before_retry when a mutation reached LinkedIn and not_applied when none did. This server never retries a mutation; reads retry a network error, HTTP 429 or a 5xx at most twice. Account checks apply before every request. Campaign, group and creative filters are verified against the account before a report, and every write re-reads its account and parent entities. Unknown arguments are rejected. Requests go only to api.linkedin.com, the token endpoint and the signed upload URLs on www.linkedin.com, without following redirects, with timeouts and bounded responses. Upload URLs travel inside HMAC-signed receipts that end with the process, and the upload request carries no token. Tokens and secrets are redacted from every result and error. Budgets and bids are decimal strings in the account currency, such as "20.00" with "EUR", not micros or cents. A report needs at least one entity scope, accepts at most 20 fields and is capped at 15,000 rows; the server applies these limits before the call and says when LinkedIn drops a field instead of returning zero.

This server exposes the native LinkedIn tools of the hosted gateway, plus account discovery, a health check and offline query validation. Audience size estimates, bid and supply forecasts, matched audiences, conversion rules, lead form definitions, experiments, Page statistics and generic endpoint reads are not included in this release. Submitted lead data is never exposed. Use tools/list or server-card.json for exact schemas and the Marketing API documentation for provider details.

Hosted option

getmcpads for LinkedIn Ads manages the hosted connection and account selection. Hosted and source releases can differ. Contact: hello@getmcpads.com.

Development

npm run typecheck
npm run lint
npm run build
npm test
npm run catalog

All tests run offline with mocked fetch responses. No live account is read or changed.

Tools

Every tool is listed below. See server-card.json for complete parameter and output schemas. Every tool except linkedin_list_ad_accounts, linkedin_health_check and linkedin_validate_query takes a configured adAccountId.

Tool

Purpose

linkedin_health_check

Check the token, the configured accounts it reaches, the reporting endpoint and the API version, without returning the token

linkedin_list_ad_accounts

List the configured ad accounts the member can reach, with currency, status and serving status

linkedin_get_account_details

Read one ad account in full, with the members who hold a role on it

linkedin_get_campaign_groups

List campaign groups with budget, schedule and serving status

linkedin_get_campaigns

List campaigns with status, objective, format, bid, budget and schedule, optionally with targeting

linkedin_get_creatives

List creatives with intended status, review verdict and serving hold reasons

linkedin_get_entity

Read one campaign group, campaign or creative and verify account ownership

linkedin_get_setup_guide

Read the account, supported formats and native write requirements before preparing changes

linkedin_get_insights

Run a report grouped by one pivot, with computed ratios

linkedin_run_statistics_report

Run a report grouped by up to three pivots at once

linkedin_get_demographics

Break delivery down by professional demographics, with names resolved and the limits stated

linkedin_get_revenue_attribution

Read CRM pipeline and closed won revenue attributed to LinkedIn advertising

linkedin_validate_query

Check a pivot and metric combination against the reporting rules, without a request

linkedin_get_delivery_status

Explain why ads are or are not serving, from the account down to the creative

linkedin_find_targeting

Look up native targeting URNs, such as countries or job titles, by name

linkedin_list_media

List the account image or video library with download URLs and processing status

linkedin_get_media

Refresh one image or video URL and verify its library association

linkedin_list_ad_creatives

List the images and videos used by ads, with the actual ad names and landing pages

Disabled by default. Calls preview unless explicitly confirmed. Check the configuration and exact schema before use.

Tool

Purpose

linkedin_create_campaign_group

Create a DRAFT campaign group

linkedin_create_campaign

Create a DRAFT text ad or sponsored content campaign with budget, bid, targeting and schedule

linkedin_create_text_ad

Create a DRAFT text ad with an image from the account library

linkedin_create_media_ad

Create a DRAFT sponsored image or video ad on a dark post

linkedin_update_entity

Rename, pause or archive, or edit budget, bid, schedule, targeting or text ad content

linkedin_rename_campaign_group

Rename a campaign group, and nothing else

linkedin_rename_campaign

Rename a campaign, and nothing else

linkedin_rename_ad

Rename an ad (creative), and nothing else

linkedin_rename_ad_account

Rename the ad account, and nothing else

linkedin_duplicate_ad

Copy an ad into a verified campaign as DRAFT

linkedin_delete_draft_ad

Delete one DRAFT ad, without touching its post or media

linkedin_initialize_upload

Start an image or video upload to the account library and return a signed receipt

linkedin_upload_part

Upload one part of the file to LinkedIn's signed upload URL

linkedin_finalize_upload

Finalize a video once every part is uploaded

linkedin_update_media

Rename or archive a library image or video

Resource

Content

linkedin://manifest

Configured accounts, API version, entity hierarchy and safety rules

linkedin://metrics

The metric catalog, with formulas of computed ratios and the pivots each metric is unavailable with

linkedin://pivots

Pivots and the finder that serves each one

linkedin://reporting-rules

Scoping, row cap, retention, freshness, demographic limits and throttling

linkedin://targeting

Shape of the targeting criteria, lookup and audience limits

linkedin://recipes

Tool sequences for common questions

License

Apache License 2.0. See NOTICE.

More from getmcpads

Meta Ads · Google Ads · Google Analytics 4 · Google Search Console · TikTok Ads · Pinterest Ads · X Ads

Maintained by Emmanuel at getmcpads. Questions: hello@getmcpads.com.

Available Tools

18 tools
linkedin_find_targetinglinkedin find targetingB
Read-onlyIdempotent

Look up native targeting URNs such as countries by name.

NameRequiredDescriptionDefault
facetNoNative targeting facet URN; defaults to location targeting.urn:li:adTargetingFacet:locations
queryYesSearch text used by the native targeting lookup.
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true, and destructiveHint=false, so the description is not responsible for the safety profile. Beyond annotations it adds essentially nothing – no indication of whether results are capped, how partial-name matching behaves, or whether multiple facets can be queried in one call. The phrase "such as countries" is the only behavioral hint, quietly confirming the default location facet.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with zero filler and no redundant restatement of the title. It is efficient, though its terseness borders on under-specification rather than optimal density.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists and annotations are rich, so the description needn't explain return values or safety. However, the one genuinely agent-relevant fact – that the facet parameter generalizes the lookup beyond locations – is left entirely to the schema, and no relationship to sibling lookup tools is established.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all three parameters are already documented, including the facet default URN and the adAccountId allowlist constraint. The description only restates the query concept ("by name") and never explains that the facet parameter makes this tool generic to skills, industries, and other facets. Baseline 3 applies when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource combination ("look up native targeting URNs") and gives a concrete example ("such as countries by name"), so the agent knows this resolves human-readable names into LinkedIn targeting URNs. It does not distinguish itself from adjacent lookup tools like linkedin_get_entity or linkedin_validate_query, which is the only reason it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: an agent can infer it should call this before any tool that needs a targeting URN. There is no explicit statement of when-not-to-use, no mention of how it relates to linkedin_validate_query or linkedin_list_ad_accounts, and no prerequisites (e.g. that adAccountId must be configured) are surfaced.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_get_account_detailslinkedin get account detailsA
Read-onlyIdempotent

Read one LinkedIn ad account in full, with the members who hold a role on it. Roles decide what the connection can do, so a read that fails on one account and works on another is usually a role, not a scope.

NameRequiredDescriptionDefault
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.
includeUsersNoAlso list the account users and their roles. On by default.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so safety is covered. The description contributes one genuinely non-obvious trait — that per-account role grants, not scopes, drive failures — which is useful diagnostic context, but it omits anything about cost, rate limits, or response shape.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero padding, with the core read action front-loaded before the troubleshooting note. Every sentence carries distinct information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need no explanation, and the description covers purpose, included data, and failure semantics. Only the absence of any explicit routing to sibling tools keeps it from a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both parameters (adAccountId with its LINKEDIN_ADS_ACCOUNT_IDS constraint, and includeUsers defaulting on) are already fully documented. The description's mention of 'members who hold a role' loosely maps to includeUsers but adds no syntax or format detail beyond the schema. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Read one LinkedIn ad account in full') and adds the scope detail that member roles are included. It implicitly contrasts with the list-style sibling but never names linkedin_list_ad_accounts, so the differentiation is inferable rather than explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The single-account framing plus the note that failures are usually role-based gives clear context for when this read is the right call versus a list operation. It stops short of naming an alternative tool or stating exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_get_campaign_groupslinkedin get campaign groupsA
Read-onlyIdempotent

List campaign groups in a LinkedIn ad account, with budget, schedule and serving status. On LinkedIn the campaign group is where a shared budget and a bid strategy live, so it is the level that explains why sibling campaigns stopped together.

NameRequiredDescriptionDefault
nameNoExact campaign group names to match.
statusNoKeep only campaign groups in these native statuses.
pageSizeNoMaximum items in this page, 1 to 100. Defaults to 100.
pageTokenNoOpaque nextPageToken from the preceding response; omit for the first page.
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered. The description adds useful domain context about shared budgets and bid strategies living at this level, but says nothing about pagination behavior, result volume, or rate/permission constraints beyond what the schema states.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, both earning their place: the first front-loads what is returned, the second supplies the conceptual model. No redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, rich annotations, and full parameter documentation, the description only needs to orient the agent, which it does. The only remaining gap is explicit routing versus sibling list tools such as linkedin_get_campaigns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter including name, status, pageSize, pageToken and adAccountId is already documented in the schema. The description adds no additional semantics about filtering behavior (e.g., exact-match name arrays or status filtering), so it sits at the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List campaign groups in a LinkedIn ad account') plus the fields returned (budget, schedule, serving status). It also situates the resource in the LinkedIn hierarchy relative to campaigns. It stops short of naming the sibling list tool it complements, so sibling differentiation is implied rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The closing sentence hints at when this level is useful ('explains why sibling campaigns stopped together'), which implies a diagnostic use case. But there is no explicit when-to-use/when-not guidance and no named alternative among the many sibling list/get tools, leaving selection largely to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_get_campaignslinkedin get campaignsA
Read-onlyIdempotent

List campaigns in a LinkedIn ad account with status, objective, format, bid strategy, budget and schedule. On LinkedIn the campaign holds the targeting and the bid, and the creatives under it are the ads.

NameRequiredDescriptionDefault
nameNoExact campaign names to match.
typeNoKeep only these campaign formats, such as TEXT_AD or SPONSORED_UPDATES.
statusNoKeep only campaigns in these native statuses.
pageSizeNoMaximum items in this page, 1 to 100. Defaults to 100.
pageTokenNoOpaque nextPageToken from the preceding response; omit for the first page.
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.
campaignGroupIdNoKeep only campaigns in this campaign group of the selected account.
includeTargetingNoReturn the raw targetingCriteria object. Off by default because it is verbose.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations provide robust technical transparency (read-only, idempotent). The description adds domain-specific behavioral context by explaining that campaigns contain targeting/bidding logic and that creatives are separate, aiding in the agent's conceptual understanding of the LinkedIn ecosystem.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The definition is brief and efficient. It allocates the first sentence to scope and the second to conceptual architectural context, achieving high information density without becoming verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 100% schema coverage and rich annotations, the description does not need to cover technical details like return types or parameter syntax. It successfully covers the conceptual completeness by describing the data hierarchy (campaign holds targeting, creatives are ads).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Given that schema coverage is 100%, the baseline is 3. However, the description adds significant semantic value by clarifying the underlying business logic—specifically, that the campaign object encompasses targeting and bid strategies, which is crucial context for an agent building a complex query.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The purpose is stated clearly as 'List campaigns in a LinkedIn ad account,' immediately identifying the resource and action. The description further enhances this by listing key returned attributes like status, objective, and budget.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

While it doesn't explicitly compare itself to siblings, the description details exactly what data is returned (status, objective, format). This helps the agent determine if this tool can fulfill a user's request without needing to call a different tool (e.g., a demographics tool).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_get_creativeslinkedin get creativesA
Read-onlyIdempotent

List the creatives of a LinkedIn ad account, optionally for given campaigns. A creative is the ad itself, and it carries its own intended status, its review verdict and the reasons it is being held back.

NameRequiredDescriptionDefault
pageSizeNoMaximum items in this page, 1 to 100. Defaults to 100.
pageTokenNoOpaque nextPageToken from the preceding response; omit for the first page.
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.
campaignIdsNoSponsored campaign IDs or URNs in the selected account.
includeContentNoReturn the raw content object of each creative. Off by default.
intendedStatusesNoFilter by native configured ad statuses, not effective delivery status.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, non-destructive, so the safety profile is covered. The description adds real domain context beyond that: a creative is the ad itself and carries intended status, review verdict and hold-back reasons — information an agent could not get from the annotations or schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the operation and scope, with the second sentence earning its place by defining the returned entity. No filler or repetition of schema details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a paginated read tool with an output schema and full parameter documentation, the description supplies the entity definition and the interesting payload fields. Minor gap: no mention of pagination behavior or the relationship to the near-identical sibling tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all six parameters are already documented, including the native-vs-effective status distinction for intendedStatuses. The description only alludes to campaign scoping and adds no filter syntax or defaults beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List the creatives of a LinkedIn ad account') plus the optional campaign scoping, and defines what a creative is. It does not, however, differentiate itself from the sibling linkedin_list_ad_creatives, which reads as a near-duplicate by name.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'optionally for given campaigns' implies the filtering use case, but there is no explicit when-to-use guidance and no routing between this tool and linkedin_list_ad_creatives. Usage is inferable rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_get_delivery_statuslinkedin get delivery statusA
Read-onlyIdempotent

Explain why LinkedIn ads are or are not serving, from the account down to the creative. LinkedIn keeps a user status and a system serving status side by side, and it is almost always the second one that says why nothing is running.

NameRequiredDescriptionDefault
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.
campaignIdsNoLimit the campaign and creative scan to these campaigns.
includeCreativesNoAlso scan creatives. On by default.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the operation read-only, idempotent, non-destructive, and open-world. The description adds useful domain behavior beyond annotations: LinkedIn exposes user status and system serving status side by side, and the system status is usually the one that explains non-delivery.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences are used with no wasted wording. The diagnostic purpose is front-loaded, followed immediately by the key domain insight about user versus system status.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema, complete annotation coverage, and 100% schema descriptions, so return values, safety, and parameters are largely handled elsewhere. The description supplies the crucial diagnostic framing and status interpretation, though it could better distinguish itself from linkedin_health_check.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the parameter meanings are already fully documented. The description only loosely hints at account-to-creative scope and adds no syntax, constraints, or defaults beyond what the schema provides, making baseline 3 appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific diagnostic verb and resource: explain why LinkedIn ads are or are not serving, scoped from account to creative. It distinguishes itself from retrieval siblings by diagnostic intent, but does not explicitly name alternatives such as linkedin_health_check.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The first sentence gives a clear diagnostic context: use this when you need to understand why ads are or are not serving. It does not name alternatives or exclusions, so it falls short of the explicit sibling routing seen in a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_get_demographicslinkedin get demographicsA
Read-onlyIdempotent

Break LinkedIn delivery down by professional demographics: company, company size, industry, seniority, job title, job function or location. These are the numbers LinkedIn is bought for, and they come with limits the tool states alongside the rows.

NameRequiredDescriptionDefault
limitNoKeep only the top rows by impressions. Defaults to 50.
endDateNoInclusive end, YYYY-MM-DD. Defaults to today.
metricsNoDefaults to spend, impressions, clicks and CTR. Conversion value, carousel and reach fields are not available here.
breakdownYesWhich professional demographic to group by.
startDateYesInclusive start, YYYY-MM-DD.
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.
campaignIdsNoRestrict reporting to these campaign IDs or URNs in the selected account.
resolveNamesNoResolve the returned URNs to readable names. On by default.
campaignGroupIdsNoRestrict reporting to these owned campaign-group IDs.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false. The description adds only that limits are stated alongside rows, without specifying what those limits are or any auth/rate-limit detail. It does not contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, with the purpose front-loaded. The second sentence mixes useful context ('limits ... alongside the rows') with promotional filler ('numbers LinkedIn is bought for'), so it is concise but not waste-free.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only reporting tool with full schema coverage, annotations, and an output schema, the description gives enough to identify the breakdown capability. It omits comparison guidance to sibling reporting tools, which keeps it from a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description's list of demographic categories loosely maps to the breakdown enum, but it does not add syntax or meaning for limit, metrics, campaign filters, resolveNames, or dates beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: break LinkedIn delivery down by professional demographics, and lists the available grouping categories. It does not explicitly distinguish this from sibling reporting tools such as linkedin_get_insights or linkedin_run_statistics_report, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies the tool is for demographic breakdown reporting by naming the professional demographic dimensions. It gives no explicit when-to-use guidance, alternatives, or exclusions compared with sibling reporting tools; usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_get_entitylinkedin get entityA
Read-onlyIdempotent

Read one campaign group, campaign or creative and verify account ownership.

NameRequiredDescriptionDefault
kindYesNative resource type to read or modify.
entityIdYesNative numeric ID or sponsoredCreative URN; account ownership is verified.
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is covered. The description contributes the ownership-verification detail, which tells the agent a permission check is part of the call. It adds nothing about failure behavior when ownership fails or about openWorld-related variability, so it is a modest increment over the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short sentence that front-loads the verb and the resource scope with zero filler. It is efficient, though slightly too terse to carry usage routing or behavioral nuance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is a simple three-parameter read with 100% schema coverage, full annotations, and an output schema that covers return values. Given that, the description is adequate: it names the entity kinds and the ownership check. Minor gaps remain around choosing this over sibling list/get tools.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already documents the kind enum, the entityId pattern including the sponsoredCreative URN form, and the account ID constraint. The description only restates the ownership verification that the entityId schema description also mentions, so it adds no semantic value beyond structured fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource set (read one campaign group, campaign, or creative), which is clearly distinct from the plural list siblings such as linkedin_get_campaign_groups and linkedin_get_campaigns. It stops short of naming those siblings as alternatives, so differentiation is implied by the singular noun rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'read one' implies this is the single-entity fetch path and that the list tools cover bulk retrieval, and 'verify account ownership' hints at a post-lookup access check. However, there is no explicit when-to-use versus the list tools, no guidance on choosing between it and linkedin_get_account_details, and no preconditions spelled out beyond what the schema already encodes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_get_insightslinkedin get insightsA
Read-onlyIdempotent

Run a LinkedIn Ads report grouped by one pivot. This is the analytics finder: one pivot, any granularity, and up to 20 fields including dateRange and pivotValues. Ratios such as CTR, CPC and CPM do not exist in the API and are computed here from the raw terms.

NameRequiredDescriptionDefault
pivotNoGrouping. Defaults to CAMPAIGN. One of: ACCOUNT, CAMPAIGN_GROUP, CAMPAIGN, CREATIVE, COMPANY, SHARE, CONVERSION, MEMBER_COMPANY, MEMBER_COMPANY_SIZE, MEMBER_INDUSTRY, MEMBER_SENIORITY, MEMBER_JOB_TITLE, MEMBER_JOB_FUNCTION, MEMBER_COUNTRY_V2, MEMBER_REGION_V2, MEMBER_COUNTY, SERVING_LOCATION, PLACEMENT_NAME, IMPRESSION_DEVICE_TYPE, EVENT_STAGE, CARD_INDEX, CONVERSATION_NODE, CONVERSATION_NODE_OPTION_INDEX.
endDateNoInclusive end, YYYY-MM-DD. Defaults to today.
metricsNoMetric keys from linkedin://metrics. Defaults to spend, impressions, clicks and the ratios.
sortFieldNoNative field used to order the returned rows.
sortOrderNoAscending or descending native result ordering.
startDateYesInclusive start, YYYY-MM-DD.
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.
campaignIdsNoRestrict reporting to these campaign IDs or URNs in the selected account.
creativeIdsNoRestrict reporting to these owned creative IDs.
campaignTypeNoNative campaign format filter.
timeGranularityNoDefaults to ALL, one row for the whole range.
campaignGroupIdsNoRestrict reporting to these owned campaign-group IDs.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the bar is lower. The description adds genuinely non-structured behavior: ratios like CTR, CPC and CPM are not API-native and are computed here from raw terms, which explains why returned fields may include values absent from the metrics vocabulary. It omits row limits and pagination behavior for a report tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences with the core action front-loaded and no filler. The computed-ratios sentence earns its place; the middle sentence is somewhat redundant with the first.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 12 parameters at full schema coverage, rich annotations, and an output schema that documents return values, the description need only cover purpose and the non-obvious computed-metrics behavior, both of which it does. The unresolved sibling ambiguity is scored under usage guidelines rather than completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema carries parameter documentation and the baseline is 3. The description adds only loose framing ("one pivot, any granularity"), and its claim of "up to 20 fields" conflicts with the schema's maxItems: 40 for metrics, which could mislead about capacity; note this is a schema inconsistency, not an annotation contradiction.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: "Run a LinkedIn Ads report grouped by one pivot," and adds a scoping phrase ("the analytics finder"). It distinguishes this from entity-listing siblings, but does not name or distinguish it from linkedin_run_statistics_report or linkedin_get_demographics, which occupy overlapping territory.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: "one pivot, any granularity" tells the agent the shape of appropriate requests. There is no explicit when-to-use/when-not guidance and no routing rule pointing to linkedin_run_statistics_report or linkedin_get_demographics, so the agent must infer the choice from name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_get_medialinkedin get mediaC
Read-onlyIdempotent

Refresh one image/video URL and verify library association.

NameRequiredDescriptionDefault
mediaIdYesExact urn:li:image or urn:li:video associated with the selected account library.
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is largely covered. The description adds that the tool refreshes a URL and verifies library association, which is useful behavioral context beyond the annotations. However, it does not explain what 'refresh' means operationally (e.g., signed URL retrieval) or what verification entails.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with no wasted text. It could be slightly clearer about the tool's return behavior, but its brevity suits a simple two-parameter lookup tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich annotations, complete input schema, and an output schema, the description does not need to explain return values or safety properties. Still, it leaves a clear gap around when to choose this tool over linkedin_list_media and what exactly 'refresh' and 'verify library association' produce.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both required parameters (mediaId and adAccountId) are fully documented in the input schema. The description does not add any parameter-level details beyond what the schema already provides, so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action for a specific resource: refreshing one image/video URL and verifying its library association. However, the name 'get_media' suggests retrieving media details, while the description emphasizes 'refresh' and 'verify', leaving some ambiguity about what the tool actually returns. It does not explicitly distinguish itself from the sibling linkedin_list_media.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no explicit guidance on when to use this tool versus alternatives such as linkedin_list_media or linkedin_get_creatives. The phrase 'one image/video URL' implies a single-item lookup, but there are no stated prerequisites, exclusions, or alternative-selection rules.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_get_revenue_attributionlinkedin get revenue attributionA
Read-onlyIdempotent

Read the LinkedIn Revenue Attribution Report: pipeline and closed won revenue from the CRM, attributed to LinkedIn advertising. Only answers for accounts whose Business Manager has a CRM connected, and only over a window of 30 to 366 days.

NameRequiredDescriptionDefault
pivotsNoOne to three of ACCOUNT, CAMPAIGN_GROUP and CAMPAIGN. Defaults to CAMPAIGN.
endDateNoInclusive end, YYYY-MM-DD. Defaults to today.
startDateYesInclusive start, YYYY-MM-DD. The window must cover 30 to 366 days.
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.
campaignIdsNoRestrict reporting to these campaign IDs or URNs in the selected account.
campaignGroupIdsNoRestrict reporting to these owned campaign-group IDs.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the safety profile (read-only, idempotent, non-destructive, open-world). The description adds meaningful behavioral context beyond annotations by stating the CRM dependency and the enforced 30–366 day window, which materially affect whether and how the tool can be called.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: it starts with the report identity, then states the key eligibility constraints. Every clause contributes useful information with no wasted phrasing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given rich annotations, 100% schema coverage, and an output schema, the description covers the essential context: what report it returns, the CRM prerequisite, and the date-window limit. It could be slightly more complete with explicit sibling routing or filter behavior, but it is sufficient for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema already documents all six parameters, including defaults and constraints. The description reinforces the date-window constraint but adds no extra parameter-level meaning beyond what the schema provides, making 3 the appropriate baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific report and clearly defines its content: CRM pipeline and closed-won revenue attributed to LinkedIn advertising. This is a distinct resource from generic insights/statistics tools in the sibling list, so an agent can identify what the tool does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear eligibility and constraint guidance: the account's Business Manager must have a CRM connected, and the reporting window must be 30 to 366 days. It does not explicitly compare this tool to siblings like linkedin_get_insights or linkedin_run_statistics_report, so it falls short of full when-to-use/when-not/alternatives guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_get_setup_guidelinkedin get setup guideA
Read-onlyIdempotent

Read account, supported formats and native LinkedIn write requirements before preparing changes.

NameRequiredDescriptionDefault
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is covered. The description adds useful context that this tool surfaces native write requirements before mutation, though it omits details like rate limits or authentication behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is a single efficient sentence with the prerequisite condition front-loaded. The list of resources is compressed but readable; no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the description need not explain return values. For a simple read-only setup guide, it sufficiently conveys what is read and when to call it, though it could clarify the relationship between account, formats, and write requirements.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema fully documents adAccountId including its numeric pattern and the LINKEDIN_ADS_ACCOUNT_IDS constraint. The description adds no parameter-level details beyond what the schema already provides, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (Read) and concrete resources (account, supported formats, native LinkedIn write requirements), which separates it from sibling data-listing tools. It does not explicitly name sibling alternatives, but the purpose as a prerequisite setup/reference guide is clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear usage condition: call this before preparing changes. It does not state when not to use it or name alternatives, but the intended context is explicit enough to guide selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_health_checklinkedin health checkA
Read-onlyIdempotent

Read-only LinkedIn Ads health check. Confirms the token works, lists which configured ad accounts it can reach, checks the reporting endpoint and reports the API version header in use, without ever returning the token itself.

NameRequiredDescriptionDefault
adAccountIdNoOptional configured account to probe for reporting access. Defaults to the first reachable one.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-destructive, but the description adds real behavioral context beyond them: it enumerates the individual probes it performs and states the security guarantee that the token is never returned. It does not say what a failure looks like (error vs. a report with a failing field), which is the one relevant behavioral gap for a health check.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence that establishes read-only scope first, then lists the checks. No filler and nothing repeated from the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return shape needn't be explained, and annotations carry the safety profile; the description supplies the substantive content — what is probed and the token-non-disclosure guarantee. Only the failure/partial-success semantics are left unstated, a modest gap for a diagnostic tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single optional adAccountId is fully documented in the schema, including its default behavior. The description adds no parameter-level detail, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — a read-only LinkedIn Ads health check — and enumerates exactly what it verifies: token validity, reachable ad accounts, the reporting endpoint, and the API version header. That is clearly distinguishable from the data-retrieval siblings (get_campaigns, get_insights, list_ad_accounts) without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The framing as a health/diagnostic check gives a clear context for when to call it: verifying credentials and connectivity before running reports. It does not explicitly name alternatives or exclusions, even though linkedin_list_ad_accounts overlaps on the account-listing behavior.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_list_ad_accountslinkedin list ad accountsA
Read-onlyIdempotent

List the LinkedIn sponsored ad accounts configured in LINKEDIN_ADS_ACCOUNT_IDS that the authenticated member can reach, with currency, status and serving status. Accounts outside the configured list are never returned. Test accounts are excluded unless asked for.

NameRequiredDescriptionDefault
statusNoKeep only accounts in these native statuses.
adAccountIdsNoConfigured account IDs to list. Defaults to every configured account.
includeTestAccountsNoTest accounts never serve and never report. Off by default.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description provides highly valuable behavioral context beyond the annotations and schema. It specifically states the scope of data visibility (only configured accounts) and dictates the default handling of test accounts ('Test accounts are excluded unless asked for').

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The definition is highly concise and structured. The first sentence defines the core function, followed immediately by constraints and default behaviors, ensuring zero wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The definition is exceptionally complete. It clarifies the source of the data, the returned fields, and the specific default handling of exceptions (test accounts). Nothing necessary for a correct invocation is omitted.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage, the baseline is high. However, the description adds vital operational context that the schema lacks, specifically mentioning the source list ('LINKEDIN_ADS_ACCOUNT_IDS') and the exact subset of data returned, thus adding meaningful semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the action ('List'), the resource ('LinkedIn sponsored ad accounts'), and specific data points returned ('currency, status and serving status'). It establishes a very clear operational scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

While it doesn't name competing tools, it defines the operational boundaries: 'Accounts outside the configured list are never returned.' This acts as a strong usage guideline by setting expectations on scope and data availability.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_list_ad_creativeslinkedin list ad creativesA
Read-onlyIdempotent

List the images and playable videos used by the ads of an account, with the actual ad names. Separates landing URLs from media URLs. Does not report delivery.

NameRequiredDescriptionDefault
adIdsNoExact ad IDs to resolve instead of listing a page, up to ten.
limitNoMaximum ads scanned in this page; inspect coverage for additional data.
pageTokenNoOpaque nextPageToken from the preceding response; omit for the first page.
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this is a read-only, idempotent, open-world, non-destructive call. The description adds real value on top: it says the result pairs creatives with actual ad names, splits landing URLs from media URLs, and explicitly excludes delivery metrics. A note on pagination via pageToken/coverage would have made it a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, each earning its place: what it lists, how it structures URLs, and what it deliberately omits. The key scope statement is front-loaded and there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and full annotation coverage, the description need only frame scope and exclusions, which it does. The remaining gap is sibling disambiguation against linkedin_get_creatives and linkedin_list_media, which matters in a tool family this dense.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so adIds, limit, pageToken, and adAccountId are all fully documented in the schema, including the maxItems of 10 and the account allowlist requirement. The description adds no parameter-level detail (such as the adIds exact-resolve mode versus paging), so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (list) and resource (images and playable videos used by ads of an account), plus the notable detail that ad names are included and landing URLs are separated from media URLs. It does not explicitly distinguish itself from the sibling linkedin_get_creatives or linkedin_list_media, which an agent could easily confuse it with.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The exclusion 'Does not report delivery' implicitly routes delivery questions to linkedin_get_delivery_status, and 'list a page' (in the schema) implies adIds is the targeted lookup path. But there is no explicit statement of when to pick this over linkedin_get_creatives or linkedin_list_media, so the agent must infer the boundary.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_list_medialinkedin list mediaA
Read-onlyIdempotent

List account image/video library files with download URLs and native processing status; not ad performance.

NameRequiredDescriptionDefault
kindYesLibrary to list: images or videos.
limitNoMaximum results in this page; inspect paging/coverage for additional data.
startNoZero-based offset in the media library page.
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered. The description adds that results include download URLs and processing status, but since an output schema exists that disclosure is partly redundant, and it says nothing about permission requirements or pagination behavior beyond what the schema notes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense sentence, front-loaded with the verb and resource, ending with the disambiguating exclusion. No wasted clauses.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a full output schema, complete parameter docs and safety annotations, the definition covers nearly everything needed to call it. The one residual gap is explicit guidance on which sibling to use for ad performance data instead.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, including the images/videos enum and paging semantics, so the schema carries parameter meaning. The description adds only the notion of an 'account' library scope; baseline 3 applies when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List account image/video library files') plus what the results carry (download URLs, native processing status), and explicitly excludes the adjacent concern ('not ad performance'). An agent can separate it from linkedin_get_media, linkedin_get_creatives and linkedin_get_insights without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The trailing 'not ad performance' clause gives a clear negative steer toward the insights/statistics siblings, and 'library files' implies a browse/enumerate context. However, it never names the alternative tool to use when performance data is actually wanted, so the routing is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_run_statistics_reportlinkedin run statistics reportA
Read-onlyIdempotent

Run a LinkedIn Ads report grouped by up to three pivots at once. This is the statistics finder, the only way to cross campaign with device, or campaign group with serving location, in a single request.

NameRequiredDescriptionDefault
pivotsYesOne to three pivots. Order decides the order of pivotValues.
endDateNoInclusive end, YYYY-MM-DD. Defaults to today.
metricsNoMetric keys from linkedin://metrics. Defaults to spend, impressions, clicks and the ratios.
startDateYesInclusive start, YYYY-MM-DD.
adAccountIdYesSelected LinkedIn advertising account, numeric ID. It must be listed in LINKEDIN_ADS_ACCOUNT_IDS.
campaignIdsNoRestrict reporting to these campaign IDs or URNs in the selected account.
creativeIdsNoRestrict reporting to these owned creative IDs.
campaignTypeNoNative campaign format filter.
objectiveTypeNoNative campaign objective filter.
timeGranularityNoNative reporting aggregation interval. Defaults to ALL.
campaignGroupIdsNoRestrict reporting to these owned campaign-group IDs.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, covering the safety profile. The description adds the behavioral trait that multiple pivots are crossed in a single request, but says nothing about rate limits, async behavior, or the fact that results come from a statistics engine. With annotations doing heavy lifting, this is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with zero waste; the core capability (multi-pivot reporting) is front-loaded before the differentiating detail. Nothing is redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 100% schema coverage, an output schema, and full annotations, the description only needs to convey the multi-pivot value proposition, which it does. It could be slightly stronger by explicitly contrasting with get_insights/get_demographics, but nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all 11 parameters are documented in the schema, including the pivots ordering semantics. The description reinforces the pivot limit ('up to three pivots') but adds no syntax or format detail beyond what the schema already provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Run') and resource ('LinkedIn Ads report') with a concrete capability: grouping by up to three pivots. It also distinguishes itself from siblings by naming the unique cross-pivot combinations it enables, so an agent can tell it apart from get_insights or get_demographics.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear trigger for using it — when you need to cross pivots like campaign×device or campaign group×serving location in one request. However, it does not explicitly name the alternative tools to prefer when pivot crossing isn't needed, leaving that routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

linkedin_validate_querylinkedin validate queryA
Read-onlyIdempotent

Check a pivot and metric combination against the LinkedIn reporting rules before spending a call on it. Returns the fields that would actually be sent, the ones LinkedIn would drop, and the twenty field ceiling. Makes no request to LinkedIn.

NameRequiredDescriptionDefault
pivotsYesOne to three pivots, as a report would group them.
endDateNoInclusive end, YYYY-MM-DD. Defaults to today.
metricsYesMetric keys from linkedin://metrics.
startDateNoInclusive start, YYYY-MM-DD. Defaults to 30 days ago.
timeGranularityNoNative reporting aggregation interval. Defaults to ALL.

Output Schema

NameRequiredDescription
resultYesOriginal tool result: parsed JSON when the text is JSON, otherwise the text. Provider fields depend on the selected query.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

While annotations cover safety hints (readOnlyHint), the description provides unique behavioral context regarding the output: specifically listing that it returns 'the fields that would actually be sent, the ones LinkedIn would drop, and the twenty field ceiling.'

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is highly concise and well-structured. The core function is front-loaded, and the critical operational constraint ('Makes no request to LinkedIn') is used as a powerful concluding statement.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The definition is complete for a validation tool, covering the 'why' (reporting rules), the 'what' (pivots/metrics), the operational constraint (no API call), and the nature of the results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, meaning the schema handles the vast majority of semantic definition. The description primarily restates the nature of the inputs (pivot/metric) rather than adding unique semantic meaning beyond the schema's constraints.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Check') and resource ('pivot and metric combination') and immediately distinguishes its purpose: validating against LinkedIn reporting rules before using other tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides clear usage context by advising the user to run it 'before spending a call on it' and explicitly states that it makes 'no request to LinkedIn,' implying its use as a pre-flight safety check against fetch tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 18 tool updatesv1.0.1
    • Changedlinkedin_find_targeting2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_get_account_details2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_get_campaign_groups2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_get_campaigns2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_get_creatives2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_get_delivery_status2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_get_demographics2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_get_entity2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_get_insights2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_get_media2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_get_revenue_attribution2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_get_setup_guide2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_health_check2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_list_ad_accounts2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_list_ad_creatives2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_list_media2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_run_statistics_report2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedlinkedin_validate_query5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • removedInput schema / properties / endDate / $ref
        Removed value: -"#/properties/startDate"
      • addedInput schema / properties / endDate / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • addedInput schema / properties / endDate / type
        Added value: +"string"
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "items": {},
        -    "type": "array"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "items": {},
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
  2. 18 tool updatesv1.0.0
    • First observedlinkedin_find_targeting
    • First observedlinkedin_get_account_details
    • First observedlinkedin_get_campaign_groups
    • First observedlinkedin_get_campaigns
    • First observedlinkedin_get_creatives
    • First observedlinkedin_get_delivery_status
    • First observedlinkedin_get_demographics
    • First observedlinkedin_get_entity
    • First observedlinkedin_get_insights
    • First observedlinkedin_get_media
    • First observedlinkedin_get_revenue_attribution
    • First observedlinkedin_get_setup_guide
    • First observedlinkedin_health_check
    • First observedlinkedin_list_ad_accounts
    • First observedlinkedin_list_ad_creatives
    • First observedlinkedin_list_media
    • First observedlinkedin_run_statistics_report
    • First observedlinkedin_validate_query

TDQS

A3.6/5.0

Scored across 18 tools

Disambiguation4/5

Most tools have distinct purposes clearly separated by resource and action, especially account, campaign, creative, delivery, and media tools. Some ambiguity remains between the reporting tools (get_insights, run_statistics_report, get_demographics) and between get_creatives and list_ad_creatives, though descriptions provide guidance.

Naming Consistency5/5

All tool names use the linkedin_ prefix with snake_case and follow a predictable verb_noun pattern such as get_campaigns, list_media, run_statistics_report, and validate_query. Minor variations like health_check do not disrupt the overall consistency.

Tool Count4/5

Eighteen tools is reasonable for a LinkedIn Ads surface covering accounts, campaigns, creatives, reporting, demographics, media, and delivery diagnostics. It is slightly heavy but each tool appears to earn its place in this complex domain.

Completeness3/5

The server provides strong read, reporting, validation, and diagnostic coverage across the LinkedIn Ads hierarchy. However, it lacks write operations such as creating, updating, pausing, or adjusting campaigns, budgets, creatives, and targeting, which are notable gaps for an ads management server.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables MCP clients to read ad account, campaign, ad group, and ad data plus performance insights, and optionally create, pause, activate, or update paused campaigns, ad groups, and ads through a secured Streamable HTTP endpoint.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables multi-tenant access to the Meta Marketing API for account setup, campaign management, ad sets, creatives, audiences, reporting, and batch workflows through a JWT-protected MCP endpoint.
    10 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables MCP clients to read App Store campaign and performance data and to prepare preview-first, opt-in changes for explicitly allowlisted ad accounts.
    312 npm
    1
    Apache 2.0