Skip to main content

📌 Pinterest MCP Server Docker (pinterest-mcp-docker)

CI Security Docker Hub PyPI License: MIT

[!NOTE] Upstream Attribution: This project is a hardened, containerized fork of clugtu/pinterest-mcp originally created by Carlos Lugtu (@clugtu). This repository extends his work by adding multi-transport support (stdio & Streamable HTTP), OWASP application security hardening, non-root Docker containerization, CI/CD security pipelines, and automated multi-arch releases. See NOTICE.md for full licensing details.


🎯 Overview & Key Features

pinterest-mcp-docker is a secure, production-ready Model Context Protocol (MCP) server for the Pinterest API v5. It connects AI assistants—including Claude Desktop, Cursor, LibreChat, and custom LLM agents—directly to Pinterest.

With pinterest-mcp-docker, AI agents can autonomously manage Pinterest boards, search pins, create single and bulk pins, analyze pin performance, and retrieve profile insights using natural language prompts.

🧰 Available MCP Tools (11 Total)

Category Tool Name Description
📌 Pins create_pin Create a single Pinterest pin (via image URL or local image path)
📌 Pins bulk_create_pins Batch create up to 50 pins in a single call
📌 Pins update_pin Update a pin's metadata
📌 Pins delete_pin Delete a pin by ID
📋 Boards list_boards List all Pinterest boards in the user's account
📋 Boards create_board Create a new Pinterest board with privacy controls
📋 Boards get_board_pins List pins on a board
🔍 Search search_pins Search Pinterest pins by keyword query
📊 Analytics get_pin_analytics Retrieve impressions, saves, clicks, and engagement metrics
📊 Analytics get_account_analytics Retrieve account-level analytics
🔎 Trends get_trending Retrieve Pinterest trend data

🔒 Enterprise Security Features

  • 🛡️ SSRF Protection: Validates outbound URLs against public IP ranges (IPv4/IPv6), blocking access to loopback, private networks, CGNAT, link-local, and cloud metadata endpoints (169.254.169.254).
  • 📁 Path Traversal Guards: Restricts local image uploads to specified allowed directories (PINTEREST_ALLOWED_IMAGE_DIR), verifies canonical paths, caps file sizes (10MB default), and validates image headers (JPEG, PNG, GIF, WebP).
  • 🔑 Atomic Token Storage: Stores OAuth tokens in $XDG_STATE_HOME/pinterest-mcp/token.json with strict 0600 file permissions and 0700 parent directory permissions.
  • 🧹 Log Secret Redaction: Automatically scrubs OAuth access tokens, client secrets, and base64 payloads from server logs and error output.
  • 🐳 Hardened Docker Container: Runs on digest-pinned python:3.12-slim under unprivileged UID/GID 10001 with full --read-only rootfs compatibility and capability dropping (--cap-drop ALL).

🏗️ Architecture & Data Flow

The following diagram illustrates how AI applications interact with pinterest-mcp-docker over stdio or HTTP transport modes:

graph TD
    subgraph ClientLayer["🤖 AI Client Layer"]
        A1["Claude Desktop Client"]
        A2["Cursor / IDE Assistant"]
        A3["Custom LLM Agent"]
    end

    subgraph TransportLayer["🌐 Transport & Authentication Layer"]
        B1["Stdio Transport (IPC / Standard I/O)"]
        B2["Streamable HTTP Transport (Port 8080)"]
        AUTH["Bearer Token Middleware (hmac.compare_digest)"]
    end

    subgraph ServerCore["⚙️ Pinterest MCP Server"]
        DISPATCH["Tool Dispatcher (11 Pydantic Input Models)"]
        SEC["Security Guards (SSRF & Path Traversal)"]
        REDACT["Redacting Logger"]
        TOKENSTORE[("💾 Token State Volume (~/.local/state/pinterest-mcp)")]
    end

    subgraph ExternalAPI["☁️ Pinterest Cloud API"]
        PINAPI["Pinterest API v5 (OAuth 2.0 / REST)"]
    end

    A1 -->|"JSON-RPC / stdio"| B1
    A2 -->|"HTTP / mcp"| B2
    A3 -->|"HTTP / mcp"| B2

    B1 --> DISPATCH
    B2 --> AUTH
    AUTH -->|"Authorized"| DISPATCH

    DISPATCH --> SEC
    SEC --> REDACT
    SEC <--> TOKENSTORE
    SEC -->|"HTTPS Outbound (IP-Pinned Transport)"| PINAPI

📋 Step-by-Step Setup Guide

Follow this guide to get pinterest-mcp-docker up and running in under 5 minutes.

Step 1: Obtain Pinterest API Credentials

To connect to Pinterest API v5, you need a Client ID and Client Secret:

  1. Go to the Pinterest Developers Portal and log in.
  2. Click My Apps -> Create App.
  3. Fill in your app name and description.
  4. Copy your App ID (PINTEREST_CLIENT_ID) and App Secret Key (PINTEREST_CLIENT_SECRET).
  5. Set the Redirect URI to http://localhost:8089/callback (used during the OAuth setup flow).

Step 2: Choose Your Deployment Method

You can run pinterest-mcp-docker using Docker (recommended) or Native Python.


Option A: Running via Docker (Recommended)

Docker provides an isolated, read-only environment without requiring Python setup.

Published Docker Hub images are available at sinalkar/pinterest-mcp-docker. Pull the current release with docker pull sinalkar/pinterest-mcp-docker:latest.

Volume Mapping Overview

  • 💾 Token Persistence Volume: Saves OAuth access and refresh tokens across container restarts. Map a named volume or host directory to /home/app/.local/state/pinterest-mcp.
  • 🖼️ Local Image Folder Volume (Optional): If you want the AI agent to upload local images using image_path, mount your local image directory (e.g., -v /path/to/my/images:/home/app/images) and set PINTEREST_ALLOWED_IMAGE_DIR=/home/app/images.

1. Docker Stdio Mode (Default for Claude Desktop)

macOS / Linux (Bash / Zsh)
docker run -i --rm \
  -e PINTEREST_CLIENT_ID="your_client_id" \
  -e PINTEREST_CLIENT_SECRET="your_client_secret" \
  -e PINTEREST_ACCESS_TOKEN="your_access_token" \
  -v pinterest_token_data:/home/app/.local/state/pinterest-mcp \
  ghcr.io/sinalkar/pinterest-mcp-docker:latest
Windows (PowerShell)
docker run -i --rm `
  -e PINTEREST_CLIENT_ID="your_client_id" `
  -e PINTEREST_CLIENT_SECRET="your_client_secret" `
  -e PINTEREST_ACCESS_TOKEN="your_access_token" `
  -v pinterest_token_data:/home/app/.local/state/pinterest-mcp `
  ghcr.io/sinalkar/pinterest-mcp-docker:latest
With Local Image Directory Mounted
docker run -i --rm \
  -e PINTEREST_CLIENT_ID="your_client_id" \
  -e PINTEREST_CLIENT_SECRET="your_client_secret" \
  -e PINTEREST_ACCESS_TOKEN="your_access_token" \
  -e PINTEREST_ALLOWED_IMAGE_DIR="/home/app/images" \
  -v pinterest_token_data:/home/app/.local/state/pinterest-mcp \
  -v /path/to/your/images:/home/app/images \
  ghcr.io/sinalkar/pinterest-mcp-docker:latest

2. Docker HTTP Mode (Streamable HTTP Server)

Run as an HTTP service listening on port 8080:

docker run -d --name pinterest-mcp \
  -p 8080:8080 \
  -e MCP_TRANSPORT=http \
  -e MCP_HOST=0.0.0.0 \
  -e MCP_AUTH_TOKEN="your_secure_bearer_token" \
  -e PINTEREST_CLIENT_ID="your_client_id" \
  -e PINTEREST_CLIENT_SECRET="your_client_secret" \
  -e PINTEREST_ACCESS_TOKEN="your_access_token" \
  --read-only \
  --cap-drop ALL \
  --security-opt no-new-privileges:true \
  --tmpfs /tmp:rw,noexec,nosuid,size=64m \
  -v pinterest_token_data:/home/app/.local/state/pinterest-mcp \
  ghcr.io/sinalkar/pinterest-mcp-docker:latest

Verify health:

curl http://localhost:8080/readyz
# Output: {"status":"ready","version":"<installed package version>","transport":"http"}

3. Docker Compose Setup

  1. Copy .env.template to .env:
    cp .env.template .env
    
  2. Open .env and configure your credentials (PINTEREST_CLIENT_ID, PINTEREST_CLIENT_SECRET, etc.).
  3. Start the container:
    docker-compose up -d
    

Option B: Running Without Docker (Native Python)

Prerequisites

  • Python 3.11+ installed (python3 --version).

1. Install Package

From PyPI:
pip install pinterest-mcp-docker
From Source:
git clone https://github.com/sinalkar/pinterest-mcp-docker.git
cd pinterest-mcp-docker
pip install -e .

2. Run Interactive OAuth Setup CLI (pinterest-mcp-auth)

If you don't have pre-generated OAuth tokens, run the interactive helper CLI:

pinterest-mcp-auth

This starts a local OAuth callback listener on port 8089, opens Pinterest in your browser for authorization, and automatically saves your token to ~/.local/state/pinterest-mcp/token.json.

3. Launch Server by Platform

macOS / Linux (Bash / Zsh)
# Set environment variables
export PINTEREST_CLIENT_ID="your_client_id"
export PINTEREST_CLIENT_SECRET="your_client_secret"
export PINTEREST_ACCESS_TOKEN="your_access_token"

# Run in stdio mode (default)
pinterest-mcp

# Or run in HTTP mode
export MCP_TRANSPORT="http"
export MCP_HOST="127.0.0.1"
export MCP_PORT="8080"
pinterest-mcp
Windows (PowerShell)
# Set environment variables
$env:PINTEREST_CLIENT_ID="your_client_id"
$env:PINTEREST_CLIENT_SECRET="your_client_secret"
$env:PINTEREST_ACCESS_TOKEN="your_access_token"

# Run in stdio mode
pinterest-mcp

# Or run in HTTP mode
$env:MCP_TRANSPORT="http"
$env:MCP_HOST="127.0.0.1"
$env:MCP_PORT="8080"
pinterest-mcp
Windows (Command Prompt - cmd.exe)
set PINTEREST_CLIENT_ID=your_client_id
set PINTEREST_CLIENT_SECRET=your_client_secret
set PINTEREST_ACCESS_TOKEN=your_access_token

pinterest-mcp

💻 AI Client Configuration

Claude Desktop (claude_desktop_config.json)

Locate your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Using Docker (Recommended):

{
  "mcpServers": {
    "pinterest": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e", "PINTEREST_CLIENT_ID=your_client_id",
        "-e", "PINTEREST_CLIENT_SECRET=your_client_secret",
        "-e", "PINTEREST_ACCESS_TOKEN=your_access_token",
        "-v", "pinterest_token_data:/home/app/.local/state/pinterest-mcp",
        "ghcr.io/sinalkar/pinterest-mcp-docker:latest"
      ]
    }
  }
}

Using Native Python:

{
  "mcpServers": {
    "pinterest": {
      "command": "pinterest-mcp",
      "env": {
        "PINTEREST_CLIENT_ID": "your_client_id",
        "PINTEREST_CLIENT_SECRET": "your_client_secret",
        "PINTEREST_ACCESS_TOKEN": "your_access_token"
      }
    }
  }
}

🌐 Client Compatibility Matrix

Client Family Transport Default Endpoint Supported Auth Status Example Config / Notes
Claude Desktop stdio stdio Environment variables Implementation complete; desktop smoke test pending Command: docker or pinterest-mcp
Cursor http /mcp Bearer Token / None Automated handshake covered; client smoke test pending {"url": "http://localhost:8080/mcp", "headers": {"Authorization": "Bearer <token>"}}
VS Code (Roo/Cline) http / stdio /mcp Bearer / None Client smoke test pending Direct SSE or Streamable HTTP endpoint
Windsurf stdio / http /mcp Bearer / None Client smoke test pending Standard stdio command or HTTP endpoint
Claude Web Connectors http /mcp OAuth 2.1 / Bearer Server-side support complete; hosted smoke test pending Set MCP_OAUTH_ISSUER & MCP_RESOURCE_URL
ChatGPT Connectors http (JSON) /mcp OAuth 2.1 / Bearer Server-side support complete; hosted smoke test pending Set MCP_JSON_RESPONSE=true
Legacy SSE Clients sse / http+sse /sse Bearer / None Automated route/auth coverage; client smoke test pending SSE stream at /sse, messages post to /messages/

💻 AI Client Configuration

Claude Desktop (claude_desktop_config.json)

Locate your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Using Docker (Recommended):

{
  "mcpServers": {
    "pinterest": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e", "PINTEREST_CLIENT_ID=your_client_id",
        "-e", "PINTEREST_CLIENT_SECRET=your_client_secret",
        "-e", "PINTEREST_ACCESS_TOKEN=your_access_token",
        "-v", "pinterest_token_data:/home/app/.local/state/pinterest-mcp",
        "ghcr.io/sinalkar/pinterest-mcp-docker:latest"
      ]
    }
  }
}

Using Native Python:

{
  "mcpServers": {
    "pinterest": {
      "command": "pinterest-mcp",
      "env": {
        "PINTEREST_CLIENT_ID": "your_client_id",
        "PINTEREST_CLIENT_SECRET": "your_client_secret",
        "PINTEREST_ACCESS_TOKEN": "your_access_token"
      }
    }
  }
}

Cursor / Remote HTTP Client

To connect Cursor or a custom client to a running HTTP instance of pinterest-mcp-docker:

{
  "mcpServers": {
    "pinterest-http": {
      "url": "http://localhost:8080/mcp",
      "headers": {
        "Authorization": "Bearer your_secure_bearer_token"
      }
    }
  }
}

Legacy SSE Client Configuration

For clients requiring the 2024-11-05 HTTP+SSE transport:

{
  "mcpServers": {
    "pinterest-sse": {
      "url": "http://localhost:8080/sse"
    }
  }
}

⚙️ Environment Variables Reference

Variable Purpose Required Default Secret
MCP_TRANSPORT Transport mode (stdio, http, sse, http+sse) No stdio No
MCP_HOST Bind address for HTTP listener No 127.0.0.1 No
MCP_PORT Listen port for HTTP listener No 8080 No
MCP_PATH Streamable HTTP endpoint path No /mcp No
MCP_SSE_PATH SSE stream endpoint path No /sse No
MCP_MESSAGE_PATH SSE message posting endpoint path No /messages/ No
MCP_AUTH_TOKEN Shared Bearer authentication token Conditional None Yes
MCP_JSON_RESPONSE Return single JSON response instead of SSE stream No false No
MCP_STATELESS Sessionless mode (no per-client session state) No false No
MCP_RESUMABILITY Enable event stream resumability No false No
MCP_EVENT_STORE_MAX_EVENTS Bounded event capacity per stream No 1000 No
MCP_MAX_REQUEST_BYTES Maximum request body limit in bytes No 4194304 (4MB) No
MCP_SESSION_IDLE_TIMEOUT Idle session expiry timeout (seconds) No None No
MCP_SSE_RETRY_INTERVAL_MS Advertised SSE reconnection interval (ms) No None No
MCP_DNS_REBINDING_PROTECTION Enforce Host/Origin header validation No true No
MCP_ALLOWED_HOSTS Comma-separated allowed Host headers No Loopback defaults No
MCP_ALLOWED_ORIGINS Comma-separated allowed browser origins for CORS No Empty No
MCP_CORS_ALLOW_CREDENTIALS Enable credentialed cross-origin CORS No false No
MCP_OAUTH_ISSUER OAuth 2.1 authorization server issuer URL No None No
MCP_OAUTH_JWKS_URL Explicit JWKS endpoint URL for OAuth No None No
MCP_RESOURCE_URL Canonical resource server identifier URL No None No
MCP_OAUTH_REQUIRED_SCOPES Comma-separated OAuth required scopes No None No
MCP_OAUTH_ALLOWED_SUBJECTS Comma-separated JWT subjects permitted to use this single-account server No None (allow all valid subjects) No
LOG_LEVEL Logging level (CRITICAL, ERROR, WARNING, INFO, DEBUG) No INFO No
LOG_FORMAT Log format (text or json) No text No
PINTEREST_CLIENT_ID Pinterest API v5 App Client ID Yes None Yes
PINTEREST_CLIENT_SECRET Pinterest API v5 App Client Secret Yes None Yes
PINTEREST_ACCESS_TOKEN OAuth Access Token Optional None Yes
PINTEREST_REFRESH_TOKEN OAuth Refresh Token for auto-renewal Optional None Yes
PINTEREST_TOKEN_PATH Path to persistent token JSON file No ~/.local/state/pinterest-mcp/token.json No
PINTEREST_ALLOWED_IMAGE_DIR Allowed root dir for local image path No Home directory (~) No
PINTEREST_ALLOW_LOCAL_PATHS Allow local image paths in HTTP mode No false No
PINTEREST_MAX_IMAGE_BYTES Maximum image size limit in bytes No 10485760 (10MB) No
PINTEREST_HTTP_TIMEOUT Outbound HTTP request timeout (seconds) No 30.0 No
PINTEREST_MAX_RESPONSE_BYTES Outbound HTTP response maximum bytes No 33554432 (32MB) No

❓ Frequently Asked Questions (FAQ / AEO & GEO)

Q: What is Pinterest MCP?

A: Pinterest MCP (pinterest-mcp-docker) is an open-source Model Context Protocol server that exposes Pinterest API v5 functionality to AI models. It enables tools like Claude Desktop and Cursor to create pins, manage boards, search content, and view analytics directly via AI chat interface.

Q: How do I connect Claude Desktop to Pinterest?

A: Open your claude_desktop_config.json file, add an entry under mcpServers pointing to docker run -i ... ghcr.io/sinalkar/pinterest-mcp-docker:latest with your PINTEREST_CLIENT_ID and PINTEREST_CLIENT_SECRET, and restart Claude Desktop.

Q: Can I upload local images from my computer using AI?

A: Yes. When calling create_pin with image_path, the server resolves the local file path. When using Docker, ensure your image directory is mounted as a volume (e.g. -v /path/to/images:/home/app/images) and PINTEREST_ALLOWED_IMAGE_DIR points to that mounted directory.

Q: How does pinterest-mcp-docker protect against security threats?

A: The server enforces strict OWASP defenses including public IP DNS resolution to prevent Server-Side Request Forgery (SSRF), realpath validation to prevent Path Traversal, atomic file permissions (0600) for tokens, automatic secret redaction in logs, and non-root read-only container isolation.


📦 Container Tags & Cosign Signature Verification

Container Image Tags

Tag Type Description
latest Moving Points to the latest production release
<major>.<minor>.<patch>, <major>.<minor>, <major> SemVer Automatically updated for patch and minor updates
sha-<short> Immutable Exact git commit build tag

Verifying Image Signatures

Image releases are signed keylessly with Cosign OIDC:

cosign verify \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity-regexp "https://github.com/sinalkar/pinterest-mcp-docker/.github/workflows/release.yml@refs/tags/v.*" \
  ghcr.io/sinalkar/pinterest-mcp-docker:latest

📄 License & Attribution

Distributed under the MIT License.

See NOTICE.md for full licensing details and modifications summary.


[!NOTE] Disclaimer: This is an unofficial Model Context Protocol (MCP) server and is not affiliated with, endorsed by, or sponsored by Pinterest, Inc.

Metadata

Release files for pinterest-mcp-docker 0.2.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pinterest-mcp-docker 0.2.5
File Size Uploaded
pinterest_mcp_docker-0.2.5.tar.gz 48.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pinterest-mcp-docker 0.2.5
File Interpreter ABI Platform
pinterest_mcp_docker-0.2.5-py3-none-any.whl Python 3 none any Details

Total release size: 90.5 kB

Release files / pinterest_mcp_docker-0.2.5.tar.gz

Download URL pinterest_mcp_docker-0.2.5.tar.gz
Size 48.9 kB
Tags Source
SHA-256 checksum
How to use checksums
9686207c49fc3e737b9ad97b474a31c57ddb03676c4d8bf7a72d6b7aa3d6d5e0
BLAKE2b-256 checksum
How to use checksums
3933fb4f25ee274ac293e1f23beb5851b373557c804bf00ec79da77bd3db0ad2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 29, 2026.

Transparency log

Release files / pinterest_mcp_docker-0.2.5-py3-none-any.whl

Download URL pinterest_mcp_docker-0.2.5-py3-none-any.whl
Size 41.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
af320881f331e410cb1ea48c1be5ae211565a58a6c40e4cb159b7d34b51a12bc
BLAKE2b-256 checksum
How to use checksums
097d326e8c2b3061141ee44d81755e5518ff5880ee3899edd7b067abcb5d73d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 29, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.6

2 release files

This release

0.2.5 This release

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page