pinterest-mcp-docker 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. pinterest_mcp_docker-0.2.0/.gitignore +35 -0
  2. pinterest_mcp_docker-0.2.0/CHANGELOG.md +34 -0
  3. pinterest_mcp_docker-0.2.0/LICENSE +23 -0
  4. pinterest_mcp_docker-0.2.0/NOTICE.md +21 -0
  5. pinterest_mcp_docker-0.2.0/PKG-INFO +455 -0
  6. pinterest_mcp_docker-0.2.0/README.md +411 -0
  7. pinterest_mcp_docker-0.2.0/pyproject.toml +102 -0
  8. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/__init__.py +36 -0
  9. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/_version.py +24 -0
  10. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/app.py +84 -0
  11. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/auth.py +101 -0
  12. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/cli.py +49 -0
  13. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/client.py +386 -0
  14. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/config.py +167 -0
  15. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/http_app.py +87 -0
  16. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/logging_setup.py +112 -0
  17. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/security.py +238 -0
  18. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/server.py +11 -0
  19. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/stdio_main.py +49 -0
  20. pinterest_mcp_docker-0.2.0/src/pinterest_mcp/tools.py +374 -0
  21. pinterest_mcp_docker-0.2.0/tests/__init__.py +0 -0
  22. pinterest_mcp_docker-0.2.0/tests/test_client_respx.py +152 -0
  23. pinterest_mcp_docker-0.2.0/tests/test_config_logging.py +55 -0
  24. pinterest_mcp_docker-0.2.0/tests/test_dispatch.py +120 -0
  25. pinterest_mcp_docker-0.2.0/tests/test_security.py +133 -0
  26. pinterest_mcp_docker-0.2.0/tests/test_tools.py +145 -0
  27. pinterest_mcp_docker-0.2.0/tests/test_transport.py +90 -0
@@ -0,0 +1,35 @@
1
+ # Python & Build
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ .venv/
9
+ venv/
10
+ .pytest_cache/
11
+ .ruff_cache/
12
+ .coverage
13
+ coverage.xml
14
+ htmlcov/
15
+ *.sarif
16
+ bandit-results.json
17
+
18
+ # Local configuration & credentials
19
+ .env
20
+ .env.*
21
+ !.env.template
22
+ .pinterest_token.json
23
+
24
+ # OpenSpec workflow files
25
+ openspec/
26
+ .openspec/
27
+
28
+ # AI Agent directories & workspace metadata
29
+ .agent/
30
+ .agents/
31
+ .claude/
32
+ .codex/
33
+ .cursor/
34
+ .devin/
35
+ .gemini/
@@ -0,0 +1,34 @@
1
+ # Changelog
2
+
3
+ All notable changes to `pinterest-mcp-docker` will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.2.0] - 2026-08-02
9
+
10
+ ### ⚠️ BREAKING CHANGES
11
+
12
+ - **Token Path Location & Permissions:** Default token storage path has moved from `./.pinterest_token.json` (relative CWD) to `$XDG_STATE_HOME/pinterest-mcp/token.json` (defaulting to `~/.local/state/pinterest-mcp/token.json` on Linux/macOS and container-writable volume under `/home/app`).
13
+ - *Migration:* Existing users should move `.pinterest_token.json` to the new path, or set the `PINTEREST_TOKEN_PATH` environment variable.
14
+ - Token directory permissions are created with `0700` and token files are written atomically with `0600` file permissions.
15
+
16
+ ### Added
17
+
18
+ - **Multi-Transport Server Support:** The MCP server now supports both standard input/output (`stdio`) and Streamable HTTP (`http`) via Starlette and Uvicorn.
19
+ - **OWASP Application Security Hardening:**
20
+ - SSRF protections on `image_url` fetching with scheme allowlists, public IP DNS checks, IP-pinned HTTP transport, manual redirect handling (max 3 hops), and automatic `Authorization` header stripping across origins.
21
+ - Path traversal protections on `image_path` using `Path.resolve()`, containment checks against `PINTEREST_ALLOWED_IMAGE_DIR`, maximum file size caps, and magic-byte image format sniffing (JPEG, PNG, GIF, WebP).
22
+ - Secret redaction filter applied to all logging output and MCP error messages (`sanitize_error`).
23
+ - Bearer token authentication middleware for HTTP transport mode.
24
+ - **Pydantic Tool Input Registry:** All 11 tools are declared in a strict `ToolSpec` registry enforcing `extra="forbid"`, string/array length bounds, enum validation, `YYYY-MM-DD` date validation, and max batch caps. Removed the dead `dry_run_pin` branch.
25
+ - **Hardened Multi-Stage Docker Container:**
26
+ - Three-stage build on digest-pinned `python:3.12-slim` producing a minimal runtime image running as unprivileged user `10001` (`app`).
27
+ - Full read-only rootfs compatibility with `/tmp` tmpfs mount and container healthcheck.
28
+ - Multi-architecture builds (`linux/amd64` and `linux/arm64`).
29
+ - **Comprehensive CI/CD & Security Pipelines:**
30
+ - GitHub Actions workflows for matrix testing (Python 3.11, 3.12, 3.13), CodeQL SAST, Semgrep, Bandit, pip-audit, Trivy (FS & Container), OpenSSF Scorecard, and Dependabot.
31
+ - **Release Automation & Attribution:**
32
+ - Automated tag releases publishing to GHCR, Docker Hub, and PyPI via Trusted Publishing.
33
+ - SPDX SBOM, SLSA provenance, and keyless cosign image signatures.
34
+ - Prominent upstream attribution to Carlos Lugtu (`clugtu/pinterest-mcp`) in `NOTICE.md`, `LICENSE`, `pyproject.toml`, and OCI image labels.
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Carlos Lugtu
4
+
5
+ Copyright (c) 2026 sanjay s (modifications in this fork; see NOTICE.md)
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
@@ -0,0 +1,21 @@
1
+ # Notice
2
+
3
+ ## Upstream Project Attribution
4
+
5
+ This software is a modified derivative of **pinterest-mcp**, originally created and authored by **Carlos Lugtu** (`clugtu/pinterest-mcp`).
6
+
7
+ - **Original Project:** https://github.com/clugtu/pinterest-mcp
8
+ - **Original Author:** Carlos Lugtu
9
+ - **Original License:** MIT License
10
+
11
+ ## Fork Modifications
12
+
13
+ This repository (`sinalkar/pinterest-mcp-docker`) extends and hardens the upstream project with:
14
+
15
+ 1. **Multi-Transport Support:** Runs as stdio or Streamable HTTP (via Starlette/Uvicorn) with bearer token auth.
16
+ 2. **OWASP Security Hardening:** SSRF defenses (public IP resolution, scheme allowlist, custom IP-pinned transport, redirect policy), path traversal guards, input validation via Pydantic, token permission hardening (0600 file / 0700 dir), and error/log secret redaction.
17
+ 3. **Containerization:** Multi-stage, digest-pinned non-root Docker container with read-only rootfs compatibility and healthcheck.
18
+ 4. **CI/CD & Security Workflows:** CodeQL, Semgrep, Bandit, pip-audit, Trivy, Scorecard, and Dependabot automation.
19
+ 5. **Release Publishing:** Automated multi-arch builds (GHCR & Docker Hub), SPDX SBOM, SLSA provenance, and keyless cosign signatures.
20
+
21
+ All original copyrights are preserved in `LICENSE`.
@@ -0,0 +1,455 @@
1
+ Metadata-Version: 2.4
2
+ Name: pinterest-mcp-docker
3
+ Version: 0.2.0
4
+ Summary: Hardened, containerized MCP server for Pinterest API v5 — create pins, manage boards, track analytics
5
+ Project-URL: Homepage, https://github.com/sinalkar/pinterest-mcp-docker
6
+ Project-URL: Repository, https://github.com/sinalkar/pinterest-mcp-docker
7
+ Project-URL: Issues, https://github.com/sinalkar/pinterest-mcp-docker/issues
8
+ Project-URL: Changelog, https://github.com/sinalkar/pinterest-mcp-docker/blob/main/CHANGELOG.md
9
+ Project-URL: Upstream, https://github.com/clugtu/pinterest-mcp
10
+ Author: Carlos Lugtu
11
+ Maintainer: sanjay s
12
+ License: MIT
13
+ License-File: LICENSE
14
+ License-File: NOTICE.md
15
+ Keywords: ai,docker,mcp,model-context-protocol,pinterest,social-media
16
+ Classifier: Development Status :: 3 - Alpha
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Security
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: anyio>=4.0.0
25
+ Requires-Dist: httpx>=0.27.0
26
+ Requires-Dist: mcp>=1.9.0
27
+ Requires-Dist: pydantic-settings>=2.2.0
28
+ Requires-Dist: pydantic>=2.7.0
29
+ Requires-Dist: python-dotenv>=1.0.0
30
+ Provides-Extra: dev
31
+ Requires-Dist: bandit>=1.7.0; extra == 'dev'
32
+ Requires-Dist: pip-audit>=2.7.0; extra == 'dev'
33
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
34
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
35
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
36
+ Requires-Dist: respx>=0.21.0; extra == 'dev'
37
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
38
+ Requires-Dist: starlette>=0.37.0; extra == 'dev'
39
+ Requires-Dist: uvicorn>=0.30.0; extra == 'dev'
40
+ Provides-Extra: http
41
+ Requires-Dist: starlette>=0.37.0; extra == 'http'
42
+ Requires-Dist: uvicorn>=0.30.0; extra == 'http'
43
+ Description-Content-Type: text/markdown
44
+
45
+ # 📌 Pinterest MCP Server Docker (`pinterest-mcp-docker`)
46
+
47
+ [![CI](https://github.com/sinalkar/pinterest-mcp-docker/actions/workflows/ci.yml/badge.svg)](https://github.com/sinalkar/pinterest-mcp-docker/actions/workflows/ci.yml)
48
+ [![Security](https://github.com/sinalkar/pinterest-mcp-docker/actions/workflows/security.yml/badge.svg)](https://github.com/sinalkar/pinterest-mcp-docker/actions/workflows/security.yml)
49
+ [![Docker Image](https://img.shields.io/docker/v/sinalkar/pinterest-mcp-docker?label=Docker%20Hub)](https://hub.docker.com/r/sinalkar/pinterest-mcp-docker)
50
+ [![PyPI](https://img.shields.io/pypi/v/pinterest-mcp-docker)](https://pypi.org/project/pinterest-mcp-docker/)
51
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
52
+
53
+ > [!NOTE]
54
+ > **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.
55
+
56
+ ---
57
+
58
+ ## 🎯 Overview & Key Features
59
+
60
+ **`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.
61
+
62
+ 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.
63
+
64
+ ### 🧰 Available MCP Tools (11 Total)
65
+
66
+ | Category | Tool Name | Description |
67
+ | -------- | --------- | ----------- |
68
+ | 📌 **Pins** | `create_pin` | Create a single Pinterest pin (via image URL or local image path) |
69
+ | 📌 **Pins** | `bulk_create_pins` | Batch create up to 50 pins in a single call |
70
+ | 📌 **Pins** | `get_pin` | Retrieve detailed metadata for a specific pin ID |
71
+ | 📌 **Pins** | `delete_pin` | Delete a pin by ID |
72
+ | 📋 **Boards** | `list_boards` | List all Pinterest boards in the user's account |
73
+ | 📋 **Boards** | `create_board` | Create a new Pinterest board with privacy controls |
74
+ | 📋 **Boards** | `get_board` | Get details and metadata for a specific board ID |
75
+ | 📋 **Boards** | `delete_board` | Delete a board by ID |
76
+ | 🔍 **Search** | `search_pins` | Search Pinterest pins by keyword query |
77
+ | 📊 **Analytics** | `get_pin_analytics` | Retrieve impressions, saves, clicks, and engagement metrics |
78
+ | 👤 **User Profile** | `get_user_account` | Get authenticated user profile details |
79
+
80
+ ### 🔒 Enterprise Security Features
81
+
82
+ - 🛡️ **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`).
83
+ - 📁 **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).
84
+ - 🔑 **Atomic Token Storage:** Stores OAuth tokens in `$XDG_STATE_HOME/pinterest-mcp/token.json` with strict `0600` file permissions and `0700` parent directory permissions.
85
+ - 🧹 **Log Secret Redaction:** Automatically scrubs OAuth access tokens, client secrets, and base64 payloads from server logs and error output.
86
+ - 🐳 **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`).
87
+
88
+ ---
89
+
90
+ ## 🏗️ Architecture & Data Flow
91
+
92
+ The following diagram illustrates how AI applications interact with `pinterest-mcp-docker` over `stdio` or `HTTP` transport modes:
93
+
94
+ ```mermaid
95
+ graph TD
96
+ subgraph ClientLayer["🤖 AI Client Layer"]
97
+ A1["Claude Desktop Client"]
98
+ A2["Cursor / IDE Assistant"]
99
+ A3["Custom LLM Agent"]
100
+ end
101
+
102
+ subgraph TransportLayer["🌐 Transport & Authentication Layer"]
103
+ B1["Stdio Transport (IPC / Standard I/O)"]
104
+ B2["Streamable HTTP Transport (Port 8080)"]
105
+ AUTH["Bearer Token Middleware (hmac.compare_digest)"]
106
+ end
107
+
108
+ subgraph ServerCore["⚙️ Pinterest MCP Server"]
109
+ DISPATCH["Tool Dispatcher (11 Pydantic Input Models)"]
110
+ SEC["Security Guards (SSRF & Path Traversal)"]
111
+ REDACT["Redacting Logger"]
112
+ TOKENSTORE[("💾 Token State Volume (~/.local/state/pinterest-mcp)")]
113
+ end
114
+
115
+ subgraph ExternalAPI["☁️ Pinterest Cloud API"]
116
+ PINAPI["Pinterest API v5 (OAuth 2.0 / REST)"]
117
+ end
118
+
119
+ A1 -->|"JSON-RPC / stdio"| B1
120
+ A2 -->|"HTTP / mcp"| B2
121
+ A3 -->|"HTTP / mcp"| B2
122
+
123
+ B1 --> DISPATCH
124
+ B2 --> AUTH
125
+ AUTH -->|"Authorized"| DISPATCH
126
+
127
+ DISPATCH --> SEC
128
+ SEC --> REDACT
129
+ SEC <--> TOKENSTORE
130
+ SEC -->|"HTTPS Outbound (IP-Pinned Transport)"| PINAPI
131
+ ```
132
+
133
+ ---
134
+
135
+ ## 📋 Step-by-Step Setup Guide
136
+
137
+ Follow this guide to get `pinterest-mcp-docker` up and running in under 5 minutes.
138
+
139
+ ### Step 1: Obtain Pinterest API Credentials
140
+
141
+ To connect to Pinterest API v5, you need a Client ID and Client Secret:
142
+
143
+ 1. Go to the [Pinterest Developers Portal](https://developers.pinterest.com/) and log in.
144
+ 2. Click **My Apps** -> **Create App**.
145
+ 3. Fill in your app name and description.
146
+ 4. Copy your **App ID** (`PINTEREST_CLIENT_ID`) and **App Secret Key** (`PINTEREST_CLIENT_SECRET`).
147
+ 5. Set the **Redirect URI** to `http://localhost:8089/callback` (used during the OAuth setup flow).
148
+
149
+ ---
150
+
151
+ ### Step 2: Choose Your Deployment Method
152
+
153
+ You can run `pinterest-mcp-docker` using **Docker** (recommended) or **Native Python**.
154
+
155
+ ---
156
+
157
+ ### Option A: Running via Docker (Recommended)
158
+
159
+ Docker provides an isolated, read-only environment without requiring Python setup.
160
+
161
+ #### Volume Mapping Overview
162
+ - 💾 **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`.
163
+ - 🖼️ **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`.
164
+
165
+ #### 1. Docker Stdio Mode (Default for Claude Desktop)
166
+
167
+ ##### macOS / Linux (Bash / Zsh)
168
+ ```bash
169
+ docker run -i --rm \
170
+ -e PINTEREST_CLIENT_ID="your_client_id" \
171
+ -e PINTEREST_CLIENT_SECRET="your_client_secret" \
172
+ -e PINTEREST_ACCESS_TOKEN="your_access_token" \
173
+ -v pinterest_token_data:/home/app/.local/state/pinterest-mcp \
174
+ ghcr.io/sinalkar/pinterest-mcp-docker:latest
175
+ ```
176
+
177
+ ##### Windows (PowerShell)
178
+ ```powershell
179
+ docker run -i --rm `
180
+ -e PINTEREST_CLIENT_ID="your_client_id" `
181
+ -e PINTEREST_CLIENT_SECRET="your_client_secret" `
182
+ -e PINTEREST_ACCESS_TOKEN="your_access_token" `
183
+ -v pinterest_token_data:/home/app/.local/state/pinterest-mcp `
184
+ ghcr.io/sinalkar/pinterest-mcp-docker:latest
185
+ ```
186
+
187
+ ##### With Local Image Directory Mounted
188
+ ```bash
189
+ docker run -i --rm \
190
+ -e PINTEREST_CLIENT_ID="your_client_id" \
191
+ -e PINTEREST_CLIENT_SECRET="your_client_secret" \
192
+ -e PINTEREST_ACCESS_TOKEN="your_access_token" \
193
+ -e PINTEREST_ALLOWED_IMAGE_DIR="/home/app/images" \
194
+ -v pinterest_token_data:/home/app/.local/state/pinterest-mcp \
195
+ -v /path/to/your/images:/home/app/images \
196
+ ghcr.io/sinalkar/pinterest-mcp-docker:latest
197
+ ```
198
+
199
+ ---
200
+
201
+ #### 2. Docker HTTP Mode (Streamable HTTP Server)
202
+
203
+ Run as an HTTP service listening on port `8080`:
204
+
205
+ ```bash
206
+ docker run -d --name pinterest-mcp \
207
+ -p 8080:8080 \
208
+ -e MCP_TRANSPORT=http \
209
+ -e MCP_HOST=0.0.0.0 \
210
+ -e MCP_AUTH_TOKEN="your_secure_bearer_token" \
211
+ -e PINTEREST_CLIENT_ID="your_client_id" \
212
+ -e PINTEREST_CLIENT_SECRET="your_client_secret" \
213
+ -e PINTEREST_ACCESS_TOKEN="your_access_token" \
214
+ --read-only \
215
+ --cap-drop ALL \
216
+ --security-opt no-new-privileges:true \
217
+ --tmpfs /tmp:rw,noexec,nosuid,size=64m \
218
+ -v pinterest_token_data:/home/app/.local/state/pinterest-mcp \
219
+ ghcr.io/sinalkar/pinterest-mcp-docker:latest
220
+ ```
221
+
222
+ Verify health:
223
+ ```bash
224
+ curl http://localhost:8080/healthz
225
+ # Output: {"status":"ok","version":"0.2.0","transport":"http"}
226
+ ```
227
+
228
+ ---
229
+
230
+ #### 3. Docker Compose Setup
231
+
232
+ 1. Copy `.env.template` to `.env`:
233
+ ```bash
234
+ cp .env.template .env
235
+ ```
236
+ 2. Open `.env` and configure your credentials (`PINTEREST_CLIENT_ID`, `PINTEREST_CLIENT_SECRET`, etc.).
237
+ 3. Start the container:
238
+ ```bash
239
+ docker-compose up -d
240
+ ```
241
+
242
+ ---
243
+
244
+ ### Option B: Running Without Docker (Native Python)
245
+
246
+ #### Prerequisites
247
+ - **Python 3.11+** installed (`python3 --version`).
248
+
249
+ #### 1. Install Package
250
+
251
+ ##### From PyPI:
252
+ ```bash
253
+ pip install pinterest-mcp-docker
254
+ ```
255
+
256
+ ##### From Source:
257
+ ```bash
258
+ git clone https://github.com/sinalkar/pinterest-mcp-docker.git
259
+ cd pinterest-mcp-docker
260
+ pip install -e .
261
+ ```
262
+
263
+ #### 2. Run Interactive OAuth Setup CLI (`pinterest-mcp-auth`)
264
+
265
+ If you don't have pre-generated OAuth tokens, run the interactive helper CLI:
266
+
267
+ ```bash
268
+ pinterest-mcp-auth
269
+ ```
270
+
271
+ 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`.
272
+
273
+ #### 3. Launch Server by Platform
274
+
275
+ ##### macOS / Linux (Bash / Zsh)
276
+ ```bash
277
+ # Set environment variables
278
+ export PINTEREST_CLIENT_ID="your_client_id"
279
+ export PINTEREST_CLIENT_SECRET="your_client_secret"
280
+ export PINTEREST_ACCESS_TOKEN="your_access_token"
281
+
282
+ # Run in stdio mode (default)
283
+ pinterest-mcp
284
+
285
+ # Or run in HTTP mode
286
+ export MCP_TRANSPORT="http"
287
+ export MCP_HOST="127.0.0.1"
288
+ export MCP_PORT="8080"
289
+ pinterest-mcp
290
+ ```
291
+
292
+ ##### Windows (PowerShell)
293
+ ```powershell
294
+ # Set environment variables
295
+ $env:PINTEREST_CLIENT_ID="your_client_id"
296
+ $env:PINTEREST_CLIENT_SECRET="your_client_secret"
297
+ $env:PINTEREST_ACCESS_TOKEN="your_access_token"
298
+
299
+ # Run in stdio mode
300
+ pinterest-mcp
301
+
302
+ # Or run in HTTP mode
303
+ $env:MCP_TRANSPORT="http"
304
+ $env:MCP_HOST="127.0.0.1"
305
+ $env:MCP_PORT="8080"
306
+ pinterest-mcp
307
+ ```
308
+
309
+ ##### Windows (Command Prompt - `cmd.exe`)
310
+ ```cmd
311
+ set PINTEREST_CLIENT_ID=your_client_id
312
+ set PINTEREST_CLIENT_SECRET=your_client_secret
313
+ set PINTEREST_ACCESS_TOKEN=your_access_token
314
+
315
+ pinterest-mcp
316
+ ```
317
+
318
+ ---
319
+
320
+ ## 💻 AI Client Configuration
321
+
322
+ ### Claude Desktop (`claude_desktop_config.json`)
323
+
324
+ Locate your Claude Desktop config file:
325
+ - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
326
+ - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
327
+
328
+ #### Using Docker (Recommended):
329
+ ```json
330
+ {
331
+ "mcpServers": {
332
+ "pinterest": {
333
+ "command": "docker",
334
+ "args": [
335
+ "run",
336
+ "-i",
337
+ "--rm",
338
+ "-e", "PINTEREST_CLIENT_ID=your_client_id",
339
+ "-e", "PINTEREST_CLIENT_SECRET=your_client_secret",
340
+ "-e", "PINTEREST_ACCESS_TOKEN=your_access_token",
341
+ "-v", "pinterest_token_data:/home/app/.local/state/pinterest-mcp",
342
+ "ghcr.io/sinalkar/pinterest-mcp-docker:latest"
343
+ ]
344
+ }
345
+ }
346
+ }
347
+ ```
348
+
349
+ #### Using Native Python:
350
+ ```json
351
+ {
352
+ "mcpServers": {
353
+ "pinterest": {
354
+ "command": "pinterest-mcp",
355
+ "env": {
356
+ "PINTEREST_CLIENT_ID": "your_client_id",
357
+ "PINTEREST_CLIENT_SECRET": "your_client_secret",
358
+ "PINTEREST_ACCESS_TOKEN": "your_access_token"
359
+ }
360
+ }
361
+ }
362
+ }
363
+ ```
364
+
365
+ ---
366
+
367
+ ### Cursor / Remote HTTP Client
368
+
369
+ To connect Cursor or a custom client to a running HTTP instance of `pinterest-mcp-docker`:
370
+
371
+ ```json
372
+ {
373
+ "mcpServers": {
374
+ "pinterest-http": {
375
+ "url": "http://localhost:8080/mcp",
376
+ "headers": {
377
+ "Authorization": "Bearer your_secure_bearer_token"
378
+ }
379
+ }
380
+ }
381
+ }
382
+ ```
383
+
384
+ ---
385
+
386
+ ## ⚙️ Environment Variables Reference
387
+
388
+ | Variable | Purpose | Required | Default | Secret |
389
+ | -------- | ------- | -------- | ------- | ------ |
390
+ | `PINTEREST_CLIENT_ID` | Pinterest API v5 App Client ID | **Yes** | None | **Yes** |
391
+ | `PINTEREST_CLIENT_SECRET` | Pinterest API v5 App Client Secret | **Yes** | None | **Yes** |
392
+ | `PINTEREST_ACCESS_TOKEN` | OAuth Access Token | Optional | None | **Yes** |
393
+ | `PINTEREST_REFRESH_TOKEN` | OAuth Refresh Token for auto-renewal | Optional | None | **Yes** |
394
+ | `MCP_TRANSPORT` | Transport mode (`stdio` or `http`) | No | `stdio` | No |
395
+ | `MCP_HOST` | Bind address for HTTP mode | No | `127.0.0.1` | No |
396
+ | `MCP_PORT` | Listen port for HTTP mode | No | `8080` | No |
397
+ | `MCP_PATH` | Endpoint path for HTTP route | No | `/mcp` | No |
398
+ | `MCP_AUTH_TOKEN` | Bearer token for HTTP mode | Conditional | None | **Yes** |
399
+ | `PINTEREST_TOKEN_PATH` | Path to persistent token JSON file | No | `~/.local/state/pinterest-mcp/token.json` | No |
400
+ | `PINTEREST_ALLOWED_IMAGE_DIR` | Allowed root dir for local image path | No | Home directory (`~`) | No |
401
+ | `PINTEREST_ALLOW_LOCAL_PATHS` | Allow local image paths in HTTP mode | No | `false` | No |
402
+ | `PINTEREST_MAX_IMAGE_BYTES` | Maximum image size limit in bytes | No | `10485760` (10MB) | No |
403
+ | `PINTEREST_HTTP_TIMEOUT` | Outbound HTTP request timeout (seconds) | No | `30.0` | No |
404
+ | `LOG_LEVEL` | Logging level (`INFO`, `DEBUG`, etc.) | No | `INFO` | No |
405
+ | `LOG_FORMAT` | Log format (`text` or `json`) | No | `text` | No |
406
+
407
+ ---
408
+
409
+ ## ❓ Frequently Asked Questions (FAQ / AEO & GEO)
410
+
411
+ ### Q: What is Pinterest MCP?
412
+ **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.
413
+
414
+ ### Q: How do I connect Claude Desktop to Pinterest?
415
+ **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.
416
+
417
+ ### Q: Can I upload local images from my computer using AI?
418
+ **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.
419
+
420
+ ### Q: How does `pinterest-mcp-docker` protect against security threats?
421
+ **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.
422
+
423
+ ---
424
+
425
+ ## 📦 Container Tags & Cosign Signature Verification
426
+
427
+ ### Container Image Tags
428
+
429
+ | Tag | Type | Description |
430
+ | --- | ---- | ----------- |
431
+ | `latest` | Moving | Points to the latest production release |
432
+ | `0.2.0`, `0.2`, `0` | SemVer | Automatically updated for patch and minor updates |
433
+ | `sha-<short>` | Immutable | Exact git commit build tag |
434
+
435
+ ### Verifying Image Signatures
436
+
437
+ Image releases are signed keylessly with [Cosign](https://github.com/sigstore/cosign) OIDC:
438
+
439
+ ```bash
440
+ cosign verify \
441
+ --certificate-oidc-issuer https://token.actions.githubusercontent.com \
442
+ --certificate-identity-regexp "https://github.com/sinalkar/pinterest-mcp-docker/.github/workflows/release.yml@refs/tags/v.*" \
443
+ ghcr.io/sinalkar/pinterest-mcp-docker:latest
444
+ ```
445
+
446
+ ---
447
+
448
+ ## 📄 License & Attribution
449
+
450
+ Distributed under the **[MIT License](LICENSE)**.
451
+
452
+ - **Original Author:** Carlos Lugtu ([`clugtu/pinterest-mcp`](https://github.com/clugtu/pinterest-mcp))
453
+ - **Fork Maintainer:** sanjay s ([`sinalkar/pinterest-mcp-docker`](https://github.com/sinalkar/pinterest-mcp-docker))
454
+
455
+ See [NOTICE.md](NOTICE.md) for full licensing details and modifications summary.