Sign inSign up

sinalkar/pinterest-mcp-docker

By sinalkar

β€’Updated 23 days ago

Hardened, containerized MCP server for Pinterest API v5 β€” pins, boards, analytics

Image
Integration & delivery
0

1.6K

sinalkar/pinterest-mcp-docker repository overview

β πŸ“Œ 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`](https://github.com/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](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)
CategoryTool NameDescription
πŸ“Œ Pinscreate_pinCreate a single Pinterest pin (via image URL or local image path)
πŸ“Œ Pinsbulk_create_pinsBatch create up to 50 pins in a single call
πŸ“Œ Pinsupdate_pinUpdate a pin's metadata
πŸ“Œ Pinsdelete_pinDelete a pin by ID
πŸ“‹ Boardslist_boardsList all Pinterest boards in the user's account
πŸ“‹ Boardscreate_boardCreate a new Pinterest board with privacy controls
πŸ“‹ Boardsget_board_pinsList pins on a board
πŸ” Searchsearch_pinsSearch Pinterest pins by keyword query
πŸ“Š Analyticsget_pin_analyticsRetrieve impressions, saves, clicks, and engagement metrics
πŸ“Š Analyticsget_account_analyticsRetrieve account-level analytics
πŸ”Ž Trendsget_trendingRetrieve 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.


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
{
  "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 FamilyTransportDefault EndpointSupported AuthStatusExample Config / Notes
Claude DesktopstdiostdioEnvironment variablesImplementation complete; desktop smoke test pendingCommand: docker or pinterest-mcp
Cursorhttp/mcpBearer Token / NoneAutomated handshake covered; client smoke test pending{"url": "http://localhost:8080/mcp", "headers": {"Authorization": "Bearer <token>"}}
VS Code (Roo/Cline)http / stdio/mcpBearer / NoneClient smoke test pendingDirect SSE or Streamable HTTP endpoint
Windsurfstdio / http/mcpBearer / NoneClient smoke test pendingStandard stdio command or HTTP endpoint
Claude Web Connectorshttp/mcpOAuth 2.1 / BearerServer-side support complete; hosted smoke test pendingSet MCP_OAUTH_ISSUER & MCP_RESOURCE_URL
ChatGPT Connectorshttp (JSON)/mcpOAuth 2.1 / BearerServer-side support complete; hosted smoke test pendingSet MCP_JSON_RESPONSE=true
Legacy SSE Clientssse / http+sse/sseBearer / NoneAutomated route/auth coverage; client smoke test pendingSSE 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
{
  "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

Hosted Pinterest login is under development. The persistence and broker foundation is not yet an end-to-end hosted release; keep public user access disabled until the OpenSpec acceptance checks and GitHub Actions deployment are complete. See pending credential handoff⁠.

VariablePurposeRequiredDefaultSecret
MCP_MODEDeployment mode (local for single-user CLI/file tokens, hosted for multi-user external persistence)NolocalNo
MCP_TRANSPORTTransport mode (stdio, http, sse, http+sse)NostdioNo
MCP_HOSTBind address for HTTP listenerNo127.0.0.1No
MCP_PORTListen port for HTTP listenerNo8080No
MCP_PATHStreamable HTTP endpoint pathNo/mcpNo
MCP_SSE_PATHSSE stream endpoint pathNo/sseNo
MCP_MESSAGE_PATHSSE message posting endpoint pathNo/messages/No
DATABASE_URLPostgreSQL connection URL for hosted credential and owner persistenceRequired in hosted modeNoneYes
REDIS_URLRedis URL for hosted nonce replay protection and rate budgetsNoNoneYes
CREDENTIAL_ENCRYPTION_KEYAuthenticated encryption root key material for hosted credential storageRequired in hosted modeNoneYes
CREDENTIAL_KEY_IDKey identifier for versioned credential encryption keysNoprimaryNo
BROKER_HANDOFF_SECRETShared HMAC secret for private broker-to-ingress credential handoffRequired in hosted modeNoneYes
MCP_AUTH_TOKENShared Bearer authentication tokenConditionalNoneYes
MCP_JSON_RESPONSEReturn single JSON response instead of SSE streamNofalseNo
MCP_STATELESSSessionless mode (no per-client session state)NofalseNo
MCP_RESUMABILITYEnable event stream resumabilityNofalseNo
MCP_EVENT_STORE_MAX_EVENTSBounded event capacity per streamNo1000No
MCP_MAX_REQUEST_BYTESMaximum request body limit in bytesNo4194304 (4MB)No
MCP_SESSION_IDLE_TIMEOUTIdle session expiry timeout (seconds)NoNoneNo
MCP_SSE_RETRY_INTERVAL_MSAdvertised SSE reconnection interval (ms)NoNoneNo
MCP_DNS_REBINDING_PROTECTIONEnforce Host/Origin header validationNotrueNo
MCP_ALLOWED_HOSTSComma-separated allowed Host headersNoLoopback defaultsNo
MCP_ALLOWED_ORIGINSComma-separated allowed browser origins for CORSNoEmptyNo
MCP_CORS_ALLOW_CREDENTIALSEnable credentialed cross-origin CORSNofalseNo
MCP_OAUTH_ISSUEROAuth 2.1 authorization server issuer URLNoNoneNo
MCP_OAUTH_JWKS_URLExplicit JWKS endpoint URL for OAuthNoNoneNo
MCP_RESOURCE_URLCanonical resource server identifier URLNoNoneNo
MCP_OAUTH_REQUIRED_SCOPESComma-separated OAuth required scopesNoNoneNo
MCP_OAUTH_ALLOWED_SUBJECTSComma-separated JWT subjects permitted to use this single-account serverNoNone (allow all valid subjects)No
LOG_LEVELLogging level (CRITICAL, ERROR, WARNING, INFO, DEBUG)NoINFONo
LOG_FORMATLog format (text or json)NotextNo
PINTEREST_CLIENT_IDPinterest API v5 App Client IDYesNoneYes
PINTEREST_CLIENT_SECRETPinterest API v5 App Client SecretYesNoneYes
PINTEREST_ACCESS_TOKENOAuth Access TokenOptionalNoneYes
PINTEREST_REFRESH_TOKENOAuth Refresh Token for auto-renewalOptionalNoneYes
PINTEREST_TOKEN_PATHPath to persistent token JSON fileNo~/.local/state/pinterest-mcp/token.jsonNo
PINTEREST_ALLOWED_IMAGE_DIRAllowed root dir for local image pathNoHome directory (~)No
PINTEREST_ALLOW_LOCAL_PATHSAllow local image paths in HTTP modeNofalseNo
PINTEREST_MAX_IMAGE_BYTESMaximum image size limit in bytesNo10485760 (10MB)No
PINTEREST_HTTP_TIMEOUTOutbound HTTP request timeout (seconds)No30.0No
PINTEREST_MAX_RESPONSE_BYTESOutbound HTTP response maximum bytesNo33554432 (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
TagTypeDescription
latestMovingPoints to the latest production release
<major>.<minor>.<patch>, <major>.<minor>, <major>SemVerAutomatically updated for patch and minor updates
sha-<short>ImmutableExact 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.

Tag summary

Content type

Image

Digest

sha256:74318ae10…

Size

58 MB

Last updated

23 days ago

docker pull sinalkar/pinterest-mcp-docker