Pinterest Ads MCP
Connects to a single Pinterest ad account via the Pinterest Ads API to read performance data, run account audits, and perform guarded create/update operations for campaigns, ad groups, ads, keywords, Pins, and catalogs.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Pinterest Ads MCPaudit my Pinterest ad account and flag campaigns with declining CTR"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Pinterest Ads MCP — setup guide
Connect your AI assistant (Cursor, Claude Desktop, etc.) to one Pinterest ad account so it can read performance data, run account audits, and make guarded changes (preview first, then confirm).
You do not need to write code. You will copy settings, run a few terminal commands, click through Pinterest login once, and paste a small JSON config into your AI tool.
What this is: a small web app plus an MCP (Model Context Protocol) bridge. MCP is how compatible AI apps call structured “tools” instead of guessing from screenshots.
What this is not: a multi-brand agency dashboard, billing manager, or delete-anything admin panel. One deployment = one ad account.
Before you start — checklist
Gather these before installing:
Requirement | Why you need it |
Pinterest Business account | Ads API access is tied to business identity. |
Ad account you will manage | This server is locked to a single |
Ad account role: Admin or Campaign Manager (Analyst is read-only) | Write tools need create/update permission; Analyst → 403 on applies. |
Valid ads billing on the account (for live ads) | Pinterest may block creation or delivery without billing. |
Pinterest developer app | OAuth client ID and secret for login. |
Node.js 20+ and npm | Runs the server locally (nodejs.org). |
Terminal access on your Mac/PC | For |
Optional later:
Requirement | Why |
Vercel (or similar) account | Host the app on a URL instead of only localhost. |
Strong secrets | Protect OAuth and MCP endpoints in production. |
Related MCP server: PaidSync MCP Server
Part 1 — Local setup (recommended first)
Step 1 — Get the project on your machine
Clone or download this repository to a folder you will keep (e.g.
~/pinterest-ads-mcp).Open Terminal and go to that folder:
cd /path/to/pinterest-ads-mcp
Step 2 — Install dependencies
npm installStep 3 — Create your environment file
Copy the template:
cp .env.example .env.localOpen
.env.localin a text editor and fill in values (see Environment variables below).
Generate strong random secrets (run in Terminal, paste output into .env.local):
# 32+ characters — used to encrypt the Pinterest refresh token on disk
openssl rand -base64 32
# 16+ characters — protects the MCP HTTP endpoint
openssl rand -base64 24
# 16+ characters — signs OAuth “state” during login (CSRF protection)
openssl rand -base64 24Use different values for TOKEN_ENCRYPTION_KEY, MCP_AUTH_TOKEN, and OAUTH_STATE_SECRET.
Step 4 — Create a Pinterest developer app
Go to Pinterest Developers and sign in with the same business identity that owns the ad account.
Create an app (or use an existing one).
Note the App ID →
PINTEREST_APP_IDand App secret →PINTEREST_APP_SECRET.Add an OAuth redirect URI that matches exactly (including
httpvshttps, path, no trailing slash unless you configured one):Where you run the app
Redirect URI to register
Local (default)
http://localhost:3000/api/oauth/pinterestCloud host
https://YOUR-DOMAIN/api/oauth/pinterestMismatch is the most common setup failure (“redirect_uri mismatch”).
Enable / request access for the Ads API scopes your app needs (Pinterest’s developer console labels may vary; the server requests the list below at login).
Step 5 — Required OAuth scopes
When you click Start Pinterest OAuth on /connect, the server asks Pinterest for these scopes (comma-separated in the authorize URL):
Scope | Purpose |
| Confirm which user authorized the app. |
| Read campaigns, ad groups, ads, analytics, audit data. |
| Create/update campaigns, ads, keywords (via guarded tools). |
| Read Pin metadata linked to ads. |
| Create Pins when building new ads. |
| Board context for Pins. |
| Pin creation may require board access. |
| Catalog / shopping audit evidence. |
| Catalog-related writes if your workflows need them. |
If Pinterest shows fewer scopes after login, your developer app may not be approved for Ads API yet — fix that in the developer portal before expecting tools to work.
Step 6 — Find your ad account ID
In Pinterest Ads Manager, open the ad account you want this server to use. The account ID is often visible in the URL or account settings (numeric string). Set:
PINTEREST_AD_ACCOUNT_ID=your_numeric_ad_account_idUse pinterest_list_ad_accounts later to confirm the ID matches the connected user.
Step 7 — Start the server
npm run devYou should see Next.js running on http://localhost:3000.
Step 8 — Connect Pinterest (OAuth)
In a browser, open http://localhost:3000/connect.
Check the page:
Sandbox mode on/off should match
PINTEREST_USE_SANDBOXin.env.local(see Sandbox vs live).Ad account id should show your configured ID.
Click Start Pinterest OAuth.
Log in to Pinterest and Allow the requested permissions.
Pinterest sends you back to the app. Success looks like:
Green message: “Pinterest connected successfully.”
A Stored connection section with connected time and scope list.
No refresh token shown on the page (by design).
Where tokens live:
After OAuth, an encrypted refresh token is saved in
.data/oauth.jsonon the machine running the server.That file is secret. It is listed in
.gitignore— never commit it or paste it into chat.Decryption uses
TOKEN_ENCRYPTION_KEYfrom.env.local. If you lose the key, you must run/connectagain after generating a new key (old file becomes unusable).
Alternative (advanced): put a plain PINTEREST_REFRESH_TOKEN or PINTEREST_REFRESH_TOKEN_ENCRYPTED in env instead of using .data/oauth.json — useful for cloud hosts without persistent disk.
Part 2 — Connect your AI tool
Two supported paths. Pick one (HTTP is easier when the app stays running; stdio is fine for all-local setups).
Option A — HTTP MCP (/api/mcp)
The server exposes MCP at:
http://localhost:3000/api/mcpAuthentication:
If
MCP_AUTH_TOKENis unset, anyone who can reach the URL can use your tools — only acceptable on a locked-down machine.If
MCP_AUTH_TOKENis set:On localhost, requests without a token are still allowed (convenience for local dev).
On a public URL (e.g. Vercel), every request must include
Authorization: Bearer YOUR_MCP_AUTH_TOKENor you get 401 Unauthorized.
Cursor mcp.json example (adjust path and token):
{
"mcpServers": {
"pinterest-ads": {
"url": "http://localhost:3000/api/mcp",
"headers": {
"Authorization": "Bearer YOUR_MCP_AUTH_TOKEN"
}
}
}
}Keep npm run dev running while you use HTTP MCP locally.
For production URL:
"url": "https://YOUR-DOMAIN/api/mcp"Always use the Authorization header on non-localhost hosts.
Option B — stdio MCP (npm run stdio)
Runs MCP over standard input/output — no browser URL. Your AI app launches the process.
Cursor mcp.json example:
{
"mcpServers": {
"pinterest-ads": {
"command": "npm",
"args": ["run", "stdio"],
"cwd": "/absolute/path/to/pinterest-ads-mcp",
"env": {
"PINTEREST_APP_ID": "…",
"PINTEREST_APP_SECRET": "…",
"PINTEREST_AD_ACCOUNT_ID": "…",
"TOKEN_ENCRYPTION_KEY": "…",
"PINTEREST_USE_SANDBOX": "true"
}
}
}
}stdio does not load .env.local automatically. Either:
Put required variables in the
"env"block (as above), orExport them in your shell before Cursor starts.
OAuth for stdio: complete npm run dev once and visit /connect, or set PINTEREST_REFRESH_TOKEN in the "env" block after connecting elsewhere.
Part 3 — Optional: deploy to Vercel (or similar)
Use cloud hosting when you want MCP available without keeping your laptop on.
Push the repo to GitHub (do not commit
.env.localor.data/).Import the project in Vercel as a Next.js app.
Set all environment variables from
.env.localin the Vercel project settings.Update:
NEXT_PUBLIC_APP_URL→https://YOUR-DOMAINPINTEREST_REDIRECT_URI→https://YOUR-DOMAIN/api/oauth/pinterest
Add the same redirect URI in the Pinterest developer app.
Deploy, then visit
https://YOUR-DOMAIN/connectand complete OAuth on the deployed site.
Important for cloud (Vercel):
Vercel cannot write
.data/oauth.jsonunder/var/task. After OAuth succeeds,/connectshows a yellow One more step for Vercel panel withPINTEREST_REFRESH_TOKEN_ENCRYPTED. Copy it into Vercel → Settings → Environment Variables, then redeploy.Use the same
TOKEN_ENCRYPTION_KEYin Vercel that was set when you completed OAuth (the encrypted blob only decrypts with that key).Do not rely on
.data/on serverless; tokens must live in env vars.Set a strong
MCP_AUTH_TOKENand always send the Bearer header from your AI client.Do not share the public MCP URL publicly without that token.
Build/start commands (if your host asks):
Script | Command |
Install |
|
Build |
|
Start |
|
Environment variables
Variable | Required when | What it is | If missing / wrong |
| OAuth + API | Developer app ID | Cannot start OAuth or call API. |
| OAuth + API | Developer app secret | Token exchange fails. |
| OAuth | Must match Pinterest app setting | Redirect or token exchange errors. |
| Most tools | Single ad account for this deployment | Tools error on account resolution. |
| Always set explicitly |
| Wrong environment, confusing empty data or auth errors. |
| Storing token in | 32+ char secret; encrypts refresh token on disk | Cannot save or read OAuth file. |
| OAuth login | 16+ char HMAC secret for login CSRF |
|
| Recommended | 16+ char Bearer token for | Open MCP on public URLs; localhost still works without header. |
| Optional | Signs write “draft” tokens (defaults to | Write previews fail if neither is set. |
| Links / redirects | Base URL of this app (e.g. | Wrong redirect targets in some flows. |
| Optional dev | Plain refresh token in env | Bypasses |
| Optional cloud | Encrypted token blob + | Used instead of file store. |
Sandbox vs live (PINTEREST_USE_SANDBOX)
Setting | Behavior |
| API calls go to |
| Production API and real ad account data. |
On /connect, you can toggle sandbox OAuth vs production OAuth via the link on the page. The token exchange uses that choice. Keep PINTEREST_USE_SANDBOX aligned with how you connected; otherwise refresh and API hosts may disagree.
Default in .env.example is sandbox (true) — switch to false only when you intend to manage live ads.
What your AI can do — tools by use case
Account & structure (read)
Tool | Use |
| Account details, user summary, terms-of-service state. |
| Confirm which ad accounts the login can see vs your configured ID. |
| Campaign list and detail. |
| Ad groups, optionally filtered by campaign. |
| Ads in the account. |
| Keywords for ad groups. |
Reporting & analytics
Tool | Use |
| Quick sync stats for short date ranges (≤31 days), ≤100 entities, not hourly. |
| Start a large or slow report (custom body, or template). |
| Poll report job status and download link. |
| Valid metric column names for reports. |
| Whether conversion metrics are ready for a date. |
Tip: If sync analytics refuses the request or times out, use pinterest_create_report then pinterest_get_report.
Audit & compliance evidence
Tool | Use |
| Read-only bundle for ads-pinterest PN-* style controls (tags, catalogs, campaigns, etc.). Observations only — no “health score.” |
Targeting research
Tool | Use |
| Interests, locations, geos, audiences, etc. for planning ad groups. |
Create & change ads (guarded writes)
Nothing deletes campaigns/ads via API here. New entities default to PAUSED.
Workflow: always draft → review preview → apply with confirm: true. Draft tokens expire in about 5 minutes.
Draft tool | Apply tool | What it does |
|
| Create/update campaigns. New campaigns: objectives |
|
| Create/update ad groups. |
|
| Create a Pin (image URL or media id). |
|
| Create/update ads. |
|
| Keywords including negatives. |
|
| Set ACTIVE / PAUSED / ARCHIVED on campaign, ad group, or ad. |
Money: tool inputs/outputs use major currency (e.g. dollars); the server converts to Pinterest’s micro-currency internally.
Objectives: Pinterest is migrating to simplified objectives. You may still see legacy types (CATALOG_SALES, WEB_CONVERSION, AWARENESS, etc.) when reading old campaigns. Creating new campaigns through this server only allows SALES and LEADS. Ask your AI to map legacy setups to the new model when planning creates.
Quick verification after setup
In your AI chat (with MCP connected), ask it to run these in order:
List tools — you should see about 25+
pinterest_*tools (read, report, audit, draft/apply).pinterest_get_account— returns your ad account payload without “No Pinterest refresh token”.pinterest_audit_snapshot— returns a JSON evidence bundle (may take a few seconds).
If all three succeed, reporting and draft tools are ready to use.
Troubleshooting
Symptom | Likely cause | What to do |
redirect_uri mismatch | Pinterest app redirect ≠ | Copy the URI character-for-character into the developer app; redeploy if you changed domain. |
401 / 403 on ads tools | Missing scopes, app not approved for Ads API, or user lacks ad account role | Re-check scopes table; confirm you’re admin on |
No Pinterest refresh token / tools say not connected | Never finished OAuth, deleted | Visit |
ENOENT mkdir | Hosted on Vercel without env token storage | Redeploy with this fix, run OAuth again, copy |
Token refresh failed | Revoked app, expired refresh, sandbox/live mismatch | Re-run |
401 Unauthorized MCP request | Missing/wrong Bearer on a public URL, or wrong token on localhost | Add |
sync_request_too_large / analytics timeout | Range too long, too many IDs, or hourly granularity | Use |
Invalid create objective | Draft used | Use |
Apply failed / confirm required | Skipped draft step or expired draft | Run |
Set PINTEREST_APP_ID… on /connect | Incomplete | Fill app ID, secret, redirect URI, |
stdio tools fail immediately | Env vars not visible to subprocess | Add |
Security notes (please read)
.env.localholds app secrets. Do not email it, commit it to GitHub, or paste into Slack/ChatGPT..data/oauth.jsonis as sensitive as a password. Back up only encrypted, store offline, never in git.MCP HTTP URL on the internet is a remote control for your ad account if
MCP_AUTH_TOKENis weak or missing. Use a long random token and HTTPS.Do not paste refresh tokens,
MCP_AUTH_TOKEN, or app secrets into AI chats — even “private” threads.Who can run writes: anyone who can call your MCP server can run apply tools after a draft. Lock down network access and tokens.
This project intentionally excludes agency/business-access APIs, billing APIs, and delete tools.
NPM scripts reference
Command | Purpose |
| Local server + |
| MCP over stdio for AI apps that launch a subprocess |
| Production build (cloud deploy) |
| Run production build |
| Automated tests (optional) |
Out of scope
Multi-tenant token vaults, Pinterest Business Access / partner APIs, billing management, entity delete tools, and automated “account health scores.”
For technical architecture (OpenAPI version, libraries), see comments in the repository source.
This server cannot be deployed
Maintenance
Related MCP Connectors
Connect authorized ad accounts to AI assistants for audits, reporting, and approval-gated changes.
Build, edit and sync Google, Microsoft, Reddit and Meta ad campaigns from your assistant.
Run Google Ads and Meta Ads from ChatGPT or Claude: audit wasted spend, create and manage campaigns.
Manage Google, Meta, LinkedIn, Microsoft, TikTok, Snapchat and Reddit ads in AI chat, with approvals
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage, report, and analyze Google Ads campaigns securely with encrypted multi-client support, real-time API integrations, and audit trail logging.25 npmMIT

PaidSync MCP Serverofficial
AlicenseNot gradedqualityFmaintenanceConnects Google Ads, Meta Ads, and LinkedIn Ads to AI assistants, enabling natural language ad campaign management, reporting, and optimization across platforms.MIT- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to audit and analyze LinkedIn Campaign Manager accounts, campaigns, targeting, creatives, performance, and audience demographics without requiring a LinkedIn Developer App.MIT
- FlicenseNot gradedqualityCmaintenanceConnects AI assistants to Google Ads, Meta Ads, ChatGPT Ads, TikTok Ads and LinkedIn Ads so users can query live campaign performance, budgets and audiences in the account's own currency and prepare changes as proposals that only take effect after explicit approval. Reads run immediately, while every write is staged as an approvable proposal with before/after values, and newly created campaigns, ad sets and ads start paused.1-