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.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
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: Facebook Ads 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.
Set
CONNECT_PAGE_TOKEN(see Security notes), redeploy, then openhttps://YOUR-DOMAIN/connect?connect_token=YOUR_CONNECT_PAGE_TOKENand complete OAuth on the deployed site.
Important for cloud (Vercel):
Vercel cannot write
.data/oauth.jsonunder/var/task. Tokens must live in environment variables.TOKEN_ENCRYPTION_KEYmust already be set in Vercel before you run OAuth (same value forever for that deployment, unless you rotate and re-connect).After OAuth succeeds,
/connectshows a yellow One more step for Vercel panel with the value forPINTEREST_REFRESH_TOKEN_ENCRYPTED. Copy the entire string into Vercel → Settings → Environment Variables → addPINTEREST_REFRESH_TOKEN_ENCRYPTED→ Redeploy.Until that env var exists, MCP tools will say there is no refresh token — the yellow panel is a one-time handoff, not automatic storage.
Use the same
TOKEN_ENCRYPTION_KEYthat was active when you generated that encrypted blob. Changing the key without re-running OAuth breaks decryption.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. |
| Required on public URLs | Secret to open | Anyone can start OAuth against your Pinterest app if |
| 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)
Lock down /connect on Vercel (or any public URL)
/connect starts Pinterest login for whoever opens it. That does not let strangers control your MCP if you already stored PINTEREST_REFRESH_TOKEN_ENCRYPTED in Vercel (API calls use env, not a random visitor’s session). It does let them authorize their Pinterest user against your developer app, which is noisy, confusing, and risky during initial setup.
Fix: set a long random CONNECT_PAGE_TOKEN in Vercel env, redeploy, and never publish plain /connect. Use only:
https://YOUR-DOMAIN/connect?connect_token=YOUR_CONNECT_PAGE_TOKENAfter one successful visit, an httpOnly cookie keeps the session for about an hour so OAuth redirect still works. The Pinterest callback URL (/api/oauth/pinterest?code=…) stays public — that is required by OAuth.
Also: remove or avoid linking /connect from a public homepage; treat the gated URL like a password reset link.
Other secrets
.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.
Related MCP Connectors
Connect authorized ad accounts to AI assistants for audits, reporting, and approval-gated changes.
Open-source ad agent for LinkedIn Ads and Google Ads. Drafts campaigns, audiences and reports.
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.
Related MCP Servers
- 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-
- AlicenseNot gradedqualityBmaintenanceConnects Meta advertising accounts to AI assistants so users can query campaign performance, pull insights and metrics, and explore audiences and targeting options in natural language. It also allows creating, updating, and deleting campaigns, ad sets, ads, creatives, and lead forms, with new campaigns paused by default and write or destructive actions gated by admin permissions.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to query and manage Google Ads accounts, covering reporting metrics like ROAS, CTR and CPC, custom GAQL queries, keyword research, and campaign management such as creating campaigns, ad groups, ads and targeting. It connects Claude, ChatGPT, Cursor and other MCP clients to Google Ads data through a hosted remote server with OAuth.MIT
- AlicenseNot gradedqualityBmaintenanceConnects AI assistants to Microsoft Advertising (Bing Ads) accounts so they can query performance, pull search advertising reports, and create or optimize campaigns, ad groups, keywords, audiences, and conversion tracking through natural language. Write actions are available but new campaigns start paused and deletes stay off by default.MIT