Skip to main content
Glama
pinterest-mcp

pinterest-mcp

by aymandakirgh

pinterest-mcp

CI License: MIT

A Model Context Protocol server for the Pinterest API v5. It gives an AI assistant 35 typed tools over boards, pins, analytics, search and OAuth — runnable as a local stdio subprocess or as a hosted HTTP endpoint.

What it can do

Area

Tools

Account

Read the authenticated profile, followers, following, claimed websites

Boards

List, get, create, update, delete; sections; pins within a board or section

Pins

List, get, create, update, delete, save (repin); video upload registration

Analytics

Account-level daily metrics, top pins, top video pins, single- and multi-pin analytics

Search

Full-text search over the account's own pins and boards

OAuth

Build a consent URL, exchange the code, refresh an expired token

Escape hatch

pinterest_api_request for any v5 endpoint not wrapped above

What the Pinterest API cannot do

Worth knowing before you plan a workflow around it:

  • No public discovery search. Everything is scoped to the authenticated account. pinterest_search_my_pins searches your pins, not Pinterest at large.

  • Analytics reach back 90 days. Longer windows are rejected by Pinterest, not by this server.

  • Video pins take three steps — register the upload, PUT the file, then create the pin referencing the media id.

  • Trial access is limited. A new Pinterest app can only act on its own account until it is approved for Standard access. Everything here works under Trial for your own account; letting other people connect needs Standard.

Related MCP server: pinterest-mcp

Install

npx pinterest-mcp

Or from source:

git clone https://github.com/aymandakirgh/pinterest-mcp.git
cd pinterest-mcp
npm install
npm run build   # compiles to dist/
npm test

Getting a token

Fastest: a test token from the dashboard

Once your app is approved for Trial access, you can generate a token straight from the Pinterest dashboard and skip OAuth entirely — the quickest way to get this server working against your own account:

developers.pinterest.com/apps → Manage → Configure → Generate Access Token → pick Production (or Sandbox) → Generate

claude mcp add pinterest --env PINTEREST_ACCESS_TOKEN=your_token -- npx -y pinterest-mcp

Then ask the assistant to call pinterest_get_user_account to confirm the token and its scopes.

In the browser (easiest)

Run the HTTP transport with your app credentials set and open /auth:

PINTEREST_APP_ID=... PINTEREST_APP_SECRET=... npm run start:http
# then open http://localhost:3000/auth

Click through, approve on Pinterest, and the callback page hands you the access token, the refresh token and the exact claude mcp add command to paste. Nothing is stored server-side — the tokens are shown once and never written to disk.

Register <your-host>/auth/callback as a redirect URI on the Pinterest app first; it must match character for character.

Pinterest is the only sign-in option for its API — there is no "connect with Google" for third-party apps. If your Pinterest account itself uses Google or Facebook, pick that on Pinterest's own consent screen.

From the tools

If you would rather stay in the assistant:

  1. Create an app at developers.pinterest.com/apps and note the app id, secret and a registered redirect URI.

  2. Set PINTEREST_APP_ID, PINTEREST_APP_SECRET and PINTEREST_REDIRECT_URI.

  3. Ask the assistant to call pinterest_build_oauth_url, open the URL, approve.

  4. Copy the code from the redirect and call pinterest_exchange_oauth_code.

  5. Put the returned access_token in PINTEREST_ACCESS_TOKEN.

Access tokens last roughly 30 days; refresh tokens roughly a year. When calls start returning 401, use pinterest_refresh_access_token.

Scopes

Request only what you need — Pinterest shows the list on the consent screen.

Scope

Needed for

user_accounts:read

Profile, followers, following, account analytics

boards:read / boards:write

Reading / modifying boards and sections

boards:read_secret / boards:write_secret

The same, for secret boards

pins:read / pins:write

Reading / modifying pins, and pin analytics

pins:read_secret / pins:write_secret

The same, for pins on secret boards

The OAuth tool defaults to user_accounts:read, boards:read, boards:write, pins:read, pins:write.

Use it with Claude Code

claude mcp add pinterest --env PINTEREST_ACCESS_TOKEN=your_token -- npx -y pinterest-mcp

Use it with Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "pinterest": {
      "command": "npx",
      "args": ["-y", "pinterest-mcp"],
      "env": {
        "PINTEREST_ACCESS_TOKEN": "your_token_here"
      }
    }
  }
}

Let anyone connect their own account (OAuth)

Run with app credentials and the server becomes a remote MCP server with OAuth 2.1. A user adds the URL in their client, clicks Connect, approves on Pinterest, and is done — no token ever passes through their hands.

PINTEREST_APP_ID=... PINTEREST_APP_SECRET=... \
MCP_AUTH_SECRET=$(openssl rand -hex 32) \
PUBLIC_BASE_URL=https://your-host \
npm run start:http

Register https://your-host/oauth/pinterest/callback as a redirect URI on the Pinterest app, then point a client at https://your-host/mcp.

The client never receives a Pinterest token. It gets one minted here, with the Pinterest credential sealed inside it, so a single deployment can serve many people's accounts without any of them seeing another's.

Endpoint

Purpose

/.well-known/oauth-protected-resource

RFC 9728 — names the authorization server

/.well-known/oauth-authorization-server

RFC 8414 — endpoints, scopes, PKCE support

/register

RFC 7591 dynamic client registration

/authorize

Starts the flow; hands off to Pinterest

/oauth/pinterest/callback

Where Pinterest returns

/token

authorization_code and refresh_token grants

PKCE (S256) is mandatory, plain is refused. Authorization codes are single-use and live ten minutes. The iss parameter is returned per RFC 9207 so clients can detect an authorization-server mix-up. An unauthenticated POST /mcp answers 401 with a WWW-Authenticate header pointing at the resource metadata, which is what triggers a client to begin the flow.

Every token — codes, access, refresh, even client ids — is an AES-256-GCM envelope carrying its own payload and expiry, so there is no session store or database. The tradeoff: revocation means rotating MCP_AUTH_SECRET, which invalidates everything at once.

This needs Pinterest Standard access. Under Trial access, Pinterest only authorizes the app owner's own account, so the flow works but nobody else can complete it. Standard access requires an approved Trial app, compliance with the Developer Guidelines, and a video of the app using the API — see access tiers.

Run it hosted

A live instance runs on Railway:

https://pinterest-mcp-http-production.up.railway.app/mcp

It holds no credentials of its own — every caller supplies their own Pinterest token per request, and GET /health reports default_token_configured: false to prove it. Treat it as a convenience for trying the server out; run your own instance for anything that matters.

The HTTP transport turns the same server into a remote MCP endpoint:

npm run start:http     # POST /mcp, GET /health

It is stateless — each request builds its own server, transport and API client, then tears them down. Callers pass their own Pinterest token per request, so one deployment can serve several accounts without a caller's credentials leaking into another's session:

curl -X POST https://your-host/mcp \
  -H 'Authorization: Bearer <pinterest_access_token>' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

X-Pinterest-Access-Token works too, for clients that already use Authorization for their own gateway. If neither is present the server falls back to PINTEREST_ACCESS_TOKEN, and returns 401 if that is unset as well.

Docker

docker build -t pinterest-mcp .
docker run -p 3000:3000 -e PINTEREST_ACCESS_TOKEN=your_token pinterest-mcp

The image is a two-stage build running as the unprivileged node user.

Configuration

Variable

Default

Purpose

PINTEREST_ACCESS_TOKEN

—

Token the server acts with. Optional: without it only the OAuth tools work.

PINTEREST_APP_ID

—

App id, for the OAuth tools.

PINTEREST_APP_SECRET

—

App secret, for the OAuth tools.

PINTEREST_REDIRECT_URI

—

Must match a URI registered on the app exactly.

PINTEREST_SANDBOX

0

Set to 1 to target the Pinterest sandbox.

PINTEREST_API_BASE_URL

production v5

Override the API root outright.

PINTEREST_MAX_RETRIES

3

Attempts for retryable failures (429 / 5xx).

PORT

3000

HTTP transport only.

PUBLIC_BASE_URL

derived from the request

Absolute origin of the deployment. Used for OAuth metadata and callback URLs; set it behind a proxy.

MCP_AUTH_SECRET

random per boot

Seals the OAuth tokens this server issues. Required for a hosted deployment — without it, issued tokens die on restart.

The server starts whether or not a token is present, so an assistant can always reach the OAuth tools to obtain one.

Design notes

  • Errors are tool results, not exceptions. A Pinterest failure comes back as an isError result carrying the status, Pinterest's own message, and a hint naming the likely fix — a missing scope, an expired token, a bad id. Agents can act on that; a thrown exception just aborts the turn.

  • 429s and 5xx are retried with exponential backoff, honouring Retry-After up to a 30-second cap so a hostile header cannot stall a call.

  • Destructive tools are annotated. pinterest_delete_board and pinterest_delete_pin carry destructiveHint, so clients can gate them behind confirmation. Deleting a board deletes its pins too.

  • Media shapes are a discriminated union, so the model is told which fields go together rather than discovering it from a 400.

Development

npm run build       # compile
npm run dev         # compile in watch mode
npm run typecheck   # types only, no emit
npm test            # unit tests + a real MCP handshake over stdio

Tests cover the client (auth, query building, retries, error shaping) and boot the actual server over stdio to assert the tool surface, schemas and annotations. No network access required.

Contributing

Issues and pull requests are welcome. Adding an endpoint is usually one function in the relevant src/tools/*.ts module.

License

MIT

Available Tools

35 tools
pinterest_api_requestCall any Pinterest v5 endpointA

Escape hatch: issue an arbitrary request against the Pinterest API v5 using the configured token. Use this only for endpoints no dedicated tool covers — ad accounts, catalogs, audiences, conversion events. Prefer the specific tools when one exists: they validate input and explain failures. Path is relative to https://api.pinterest.com/v5.

Inputs: path (required), body, query, method.

pinterest_build_oauth_urlBuild an OAuth authorization URLA
Read-only

Build the Pinterest consent URL to open in a browser. The user approves, Pinterest redirects to your redirect_uri with a code query parameter, and you exchange that code with pinterest_exchange_oauth_code. Makes no network call.

Inputs: state, app_id, scopes, redirect_uri.

pinterest_create_boardCreate boardA

Create a new board on the authenticated account. Scope: boards:write (boards:write_secret for SECRET boards).

Inputs: name (required), privacy, description, ad_account_id.

pinterest_create_board_sectionCreate board sectionB

Add a section to a board. Scope: boards:write.

Inputs: name (required), board_id (required), ad_account_id.

pinterest_create_pinCreate pinA

Create a pin on one of the authenticated user's boards. Requires a board_id and a media_source. Scope: pins:write (pins:write_secret for secret boards).

Inputs: board_id (required), media_source (required), link, note, +6 more.

pinterest_delete_boardDelete boardA
DestructiveIdempotent

Permanently delete a board AND every pin saved to it. This cannot be undone. Scope: boards:write.

Inputs: board_id (required), ad_account_id.

pinterest_delete_board_sectionDelete board sectionA
DestructiveIdempotent

Delete a board section. Pins in the section move back to the board root rather than being deleted. Scope: boards:write.

Inputs: board_id (required), section_id (required), ad_account_id.

pinterest_delete_pinDelete pinA
DestructiveIdempotent

Permanently delete a pin. This cannot be undone. Scope: pins:write.

Inputs: pin_id (required), ad_account_id.

pinterest_exchange_oauth_codeExchange an OAuth code for tokensA

Exchange the code from the OAuth redirect for an access token and refresh token. Access tokens last about 30 days; refresh tokens about a year. Store both securely.

Inputs: code (required), app_id, app_secret, redirect_uri.

pinterest_get_boardGet boardA
Read-only

Fetch a single board by id, including its pin and follower counts. Scope: boards:read.

Inputs: board_id (required), ad_account_id.

pinterest_get_mediaGet media upload statusA
Read-only

Check a registered upload. Status moves registered -> processing -> succeeded (or failed). Scope: pins:read.

Inputs: media_id (required).

pinterest_get_multi_pin_analyticsGet analytics for several pinsA
Read-only

Analytics for up to 100 pins in one call — far cheaper than looping pinterest_get_pin_analytics. Scope: pins:read.

Inputs: pin_ids (required), end_date (required), start_date (required), app_types, +2 more.

pinterest_get_pinGet pinA
Read-only

Fetch a single pin by id, including its media, link and board. Scope: pins:read.

Inputs: pin_id (required), pin_metrics, ad_account_id.

pinterest_get_pin_analyticsGet analytics for one pinB
Read-only

Daily analytics for a single pin over a date window of up to 90 days. Scope: pins:read.

Inputs: pin_id (required), end_date (required), start_date (required), app_types, +3 more.

pinterest_get_top_pinsGet top performing pinsB
Read-only

Rank the account's pins by a metric over a date window — the tool to reach for when asked what is working. Scope: user_accounts:read and pins:read.

Inputs: end_date (required), start_date (required), sort_by, app_types, +7 more.

pinterest_get_top_video_pinsGet top performing video pinsB
Read-only

Rank the account's video pins by a video metric over a date window. Scope: user_accounts:read and pins:read.

Inputs: end_date (required), start_date (required), sort_by, app_types, +7 more.

pinterest_get_user_accountGet my accountA
Read-only

Fetch the authenticated user's account: username, id, account type, profile image and follower counts. The fastest way to verify a token works. Scope: user_accounts:read.

Inputs: ad_account_id.

pinterest_get_user_analyticsGet account analyticsA
Read-only

Daily account-level analytics over a date window of up to 90 days. Scope: user_accounts:read and pins:read.

Inputs: end_date (required), start_date (required), source, app_types, +6 more.

pinterest_list_board_pinsList pins on a boardB
Read-only

List the pins saved to a board. Scope: pins:read and boards:read.

Inputs: board_id (required), bookmark, page_size, pin_metrics, +2 more.

pinterest_list_boardsList boardsA
Read-only

List the authenticated user's boards, newest first. Scope: boards:read (plus boards:read_secret to include secret boards). Returns a bookmark cursor when more pages exist.

Inputs: privacy, bookmark, page_size, ad_account_id.

pinterest_list_board_section_pinsList pins in a board sectionA
Read-only

List the pins saved inside one section of a board. Scope: pins:read and boards:read.

Inputs: board_id (required), section_id (required), bookmark, page_size, +2 more.

pinterest_list_board_sectionsList board sectionsA
Read-only

List the sections within a board. Scope: boards:read.

Inputs: board_id (required), bookmark, page_size, ad_account_id.

pinterest_list_claimed_websitesList claimed websitesA
Read-only

List the websites claimed by the authenticated account, with their verification status. Scope: user_accounts:read.

Inputs: bookmark, page_size.

pinterest_list_followersList my followersB
Read-only

List the accounts following the authenticated user. Scope: user_accounts:read.

Inputs: bookmark, page_size.

pinterest_list_followingList who I followA
Read-only

List the users and boards the authenticated user follows. Scope: user_accounts:read.

Inputs: bookmark, feed_type, page_size.

pinterest_list_mediaList media uploadsA
Read-only

List the account's registered media uploads and their statuses. Scope: pins:read.

Inputs: bookmark, page_size.

pinterest_list_pinsList pinsB
Read-only

List the authenticated user's pins, newest first. Scope: pins:read (plus pins:read_secret for pins on secret boards).

Inputs: bookmark, pin_type, page_size, pin_filter, +4 more.

pinterest_refresh_access_tokenRefresh an access tokenA

Trade a refresh token for a fresh access token. Use this when calls start failing with 401.

Inputs: refresh_token (required), scope, app_id, app_secret.

pinterest_register_mediaRegister a video uploadA

Step 1 of video pin creation: register an upload and receive one-time S3 form fields. POST the video to upload_url with those upload_parameters as multipart form fields, poll pinterest_get_media until status is 'succeeded', then pass the media_id to pinterest_create_pin with source_type 'video_id'. Scope: pins:write.

Inputs: media_type (required).

pinterest_save_pinSave (repin) a pinA

Save an existing pin to one of the authenticated user's boards — the API equivalent of a repin. Scope: pins:write.

Inputs: pin_id (required), board_id (required), ad_account_id, board_section_id.

pinterest_search_my_boardsSearch my boardsA
Read-only

Full-text search across the authenticated user's own boards. Scope: boards:read.

Inputs: query (required), bookmark, page_size, ad_account_id.

pinterest_search_my_pinsSearch my pinsA
Read-only

Full-text search across the authenticated user's own pins. This does NOT search Pinterest globally — the v5 API exposes no public discovery search. Scope: pins:read.

Inputs: query (required), bookmark, page_size, ad_account_id.

pinterest_update_boardUpdate boardA
Idempotent

Update a board's name, description or privacy. Only the fields you pass are changed. Scope: boards:write.

Inputs: board_id (required), name, privacy, description, +1 more.

pinterest_update_board_sectionRename board sectionB
Idempotent

Rename an existing board section. Scope: boards:write.

Inputs: name (required), board_id (required), section_id (required), ad_account_id.

pinterest_update_pinUpdate pinA
Idempotent

Update a pin's text fields, link or board placement. Media cannot be changed after creation. Scope: pins:write.

Inputs: pin_id (required), link, note, title, +5 more.

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A3.8/5.0

    Scored across 35 tools

    Disambiguation5/5

    Each tool targets a distinct resource and action, with clear boundaries between boards, sections, pins, media, analytics, and OAuth flows. The few similar-sounding tools (e.g., list_board_pins vs. list_board_section_pins, get_top_pins vs. get_top_video_pins) are differentiated by precise descriptions.

    Naming Consistency5/5

    All tools follow a consistent snake_case verb_noun pattern with a uniform `pinterest_` prefix. Names like `get_user_account`, `update_board`, `list_board_pins`, and `delete_pin` are predictable and readable.

    Tool Count2/5

    With 35 tools, the surface is heavy for a single MCP server, exceeding the 25-tool threshold for being too many. While Pinterest's API is broad, many granular tools (e.g., separate board section operations) could be consolidated or left to the escape hatch `pinterest_api_request`.

    Completeness5/5

    The set covers full CRUD for boards, sections, and pins, plus media upload lifecycle, analytics, user account, followers, search, and OAuth. The `pinterest_api_request` escape hatch fills any remaining gaps for ad accounts or catalogs.

    Maintenance

    ActivityNo data
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI agents to manage Pinterest boards and pins, create and update pins, and track analytics via the Pinterest API v5.
      8
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      Enables AI agents to manage Pinterest accounts through the Pinterest API v5, including creating and editing pins, organizing boards, searching public content, and retrieving pin and account analytics.
      11
      MIT
    • A
      license
      B
      quality
      C
      maintenance
      Enables interaction with the Pinterest API v5 through natural language, covering 263 operations including pins, boards, analytics, and advertising tools, with configurable read-only and non-destructive modes.
      8
      14 npm
      MIT