Skip to main content
Glama

Personal Vinted MCP

Server MCP personale e self-hosted per preparare un annuncio da foto in ChatGPT, rivedere il riepilogo e pubblicarlo con un pulsante. Progetto indipendente, non affiliato a Vinted. Licenza Apache-2.0.

Stato: MVP sperimentale. Flusso MCP, widget, OAuth e persistenza sono implementati e testabili in simulazione. L'adattatore web per account normali è implementato ma non validato su un account reale. Gli endpoint privati possono cambiare o rifiutare le richieste. Non c'è garanzia di pubblicazione su qualsiasi account o di assenza di ban.

Vinted vieta strumenti esterni non autorizzati nei suoi termini. La documentazione pubblica trovata per pubblicare annunci è quella delle integrazioni Pro: non dimostra che un normale account abbia accesso a un'API ufficiale di pubblicazione. Per minimizzare il rischio di restrizioni, richiedi autorizzazione a Vinted o pubblica manualmente il testo preparato. Questo progetto non implementa occultamento del bot, imitazione di fingerprint, rotazione di proxy o risoluzione di CAPTCHA. Si ferma ai rifiuti del servizio.

Flusso

  1. Alleghi le foto a ChatGPT e chiedi di usare la tua app Vinted MCP.

  2. ChatGPT propone titolo, descrizione e prezzo; ti chiede ciò che non può verificare.

  3. Il server importa gli allegati localmente e legge da Vinted le opzioni valide del modulo. ChatGPT sceglie tra categoria, marca, taglia, condizioni e pacco restituiti dal server. La bozza e le foto restano locali fino alla conferma.

  4. Un riquadro mostra foto, prezzo, categoria, marca, taglia, condizioni e pacco.

  5. Premi Conferma e pubblica: solo allora parte l'invio a Vinted.

  6. Ricevi l'esito e, se confermato dall'API, il link. Gestisci il resto su Vinted.

In modalità mock il pulsante dice Conferma simulazione e non contatta Vinted. Il prezzo è una proposta del modello, non una quotazione basata su confronti di mercato. Gli ID tecnici sono gestiti tra ChatGPT e il server: non devi inserirli a mano. ChatGPT ti chiede solo informazioni sul prodotto che non può verificare (per esempio taglia o difetti). Non serve una chiave OpenAI: la preparazione è svolta da ChatGPT.

sequenceDiagram
    actor U as Tu
    participant C as ChatGPT
    participant M as Il tuo MCP
    participant V as Vinted
    U->>C: Foto e informazioni
    C->>M: import_photos
    C->>M: Cerca categorie, marca e opzioni
    M->>V: Leggi opzioni del modulo di vendita
    V-->>M: ID, nomi e campi richiesti
    M-->>C: Opzioni valide per questo oggetto
    C->>M: prepare_listing
    M-->>U: Foto e riepilogo con pulsante
    U->>M: Conferma dal widget
    M->>V: Foto, bozza remota, pubblicazione
    V-->>M: Esito
    M-->>U: Link o richiesta di verifica manuale

Related MCP server: DevSpace

Installazione guidata su Ubuntu Server

Per Ubuntu 24.04 o successivo, con systemd e accesso sudo. Copia/clona l'intero progetto sul server (il solo wheel nella cartella dist non contiene l'installer), entra nella cartella e avvia:

sudo bash install.sh

L'installer chiede il sottodominio e la porta locale, propone Caddy per HTTPS e, facoltativamente, la configurazione privata di Vinted. Mostra un riepilogo prima di installare pacchetti e servizi. Installa Python/venv e usa uv.lock per le dipendenze dell'applicazione. Supporta anche bash install.sh --help.

Percorso gestito

Contenuto

/opt/vinted-mcp

Applicazione, ambiente Python e comandi di configurazione

/etc/vinted-mcp/server.env

Configurazione e segreto OAuth generato, accessibile a root e al servizio

/var/lib/vinted-mcp

Sessione Vinted, profili, foto e database, privati dell'utente di servizio

Il processo gira come utente di sistema vinted-mcp, con avvio automatico. Il codice copiato in /opt include solo i file pubblici necessari: niente .git, .env, foto personali, sessioni o ambienti virtuali del checkout. I dati non vengono salvati nel repository.

Prima di scegliere Caddy, configura il DNS del sottodominio verso il server e rendi raggiungibili le porte 80/443. L'installer non modifica il firewall. Se hai già nginx, Apache o un altro proxy, rispondi no a Caddy e inoltra l'intero dominio HTTPS a 127.0.0.1:PORTA, comprese le rotte OAuth e /.well-known/, non soltanto /mcp. La porta locale non va aperta su Internet.

La configurazione Caddy esistente viene conservata, con backup privato prima delle modifiche. Il sito MCP viene aggiunto tramite un import dedicato; prima del reload viene validata la configurazione. Se validazione/reload falliscono, l'installer ripristina la configurazione precedente. Non sovrascrive un frammento /etc/caddy/vinted-mcp.caddy che non sia gestito dall'installer.

La prima configurazione è mock. Cookie/token vengono richiesti con input nascosto solo se scegli la configurazione Vinted. Il wizard permette di creare uno o più profili con gli ID effettivi del modulo di vendita, senza indovinarli; i profili sono facoltativi e non limitano gli articoli che puoi vendere. Puoi rispondere no alla creazione del profilo e abilitare comunque live con una sessione valida. L'attivazione live richiede una scelta separata. Salvare una sessione non verifica che Vinted la accetti e non invia annunci.

Puoi riprendere il setup o aggiornare cookie/profili con:

sudo /opt/vinted-mcp/bin/configure-vinted

Le sessioni sono salvate con permessi 600; il file di configurazione ha permessi 640. Non digitare i cookie negli argomenti del comando o nella chat. Il wizard richiede un terminale interattivo e può essere annullato con Ctrl+C.

Rilanciare sudo bash install.sh dal checkout aggiorna codice e dipendenze, conservando segreto, configurazione, modalità (anche live), foto, profili e sessione. L'installer riavvia il processo; le registrazioni dei client OAuth sono conservate nel file privato oauth-clients.json; i token sono persistenti nel database privato oauth-tokens.sqlite3, salvati solo come hash. Le autorizzazioni ancora in corso vanno riavviate dopo un aggiornamento. Non eseguire anche il vecchio servizio systemd per utente sulla stessa porta: se lo avevi creato seguendo la procedura manuale, fermalo prima con systemctl --user disable --now vinted-mcp.

Comandi utili:

sudo systemctl status vinted-mcp
sudo journalctl -u vinted-mcp -n 50
sudo grep '^MCP_OWNER_SECRET=' /etc/vinted-mcp/server.env
curl -i https://TUO-DOMINIO/mcp

Il comando grep mostra il segreto soltanto nel tuo terminale privato: non condividerne l'output. Con curl senza token è atteso 401 Unauthorized. In ChatGPT crea un server MCP personalizzato con l'URL HTTPS completo di /mcp, OAuth e registrazione dinamica. Inserisci il segreto nella pagina del tuo dominio.

Per riprendere gli invii dopo aver controllato manualmente un errore Vinted:

sudo -u vinted-mcp env VINTED_ENV_FILE=/etc/vinted-mcp/server.env \
  /opt/vinted-mcp/venv/bin/vinted-mcp unblock

La configurazione guidata non elimina i limiti dell'adattatore sperimentale descritti sotto.

Installazione locale

Python 3.12+ e uv.

uv sync --extra dev --locked
uv run vinted-mcp stdio

stdio serve ai client locali. ChatGPT remoto richiede HTTP raggiungibile tramite HTTPS; non può raggiungere direttamente il tuo localhost. Su questo PC è disponibile anche il virtualenv preparato durante lo sviluppo:

.\.venv\Scripts\vinted-mcp.exe stdio

Dati e segreti fuori da Git e OneDrive

Il codice può essere pubblico; la tua istanza e i suoi dati devono restare privati. La cartella di lavoro può essere in OneDrive: non metterci sessioni o password. Il server usa di default:

Sistema

Directory privata

Windows

%LOCALAPPDATA%\VintedMCP

Linux/macOS

$XDG_DATA_HOME/vinted-mcp, altrimenti ~/.local/share/vinted-mcp

Quella directory contiene .env, session.json, profiles.json, foto e SQLite. Non sincronizzarla nel cloud. I dati non sono cifrati dall'app: usa permessi privati del sistema e cifratura disco. Preparazione su Windows:

$vintedPrivate = Join-Path $env:LOCALAPPDATA 'VintedMCP'
New-Item -ItemType Directory -Force -Path $vintedPrivate
Copy-Item .env.example (Join-Path $vintedPrivate '.env')
.\.venv\Scripts\python.exe -c "import secrets; print(secrets.token_urlsafe(32))"

Incolla il valore generato in MCP_OWNER_SECRET nel .env privato, mai in chat. Per un'altra configurazione imposta VINTED_ENV_FILE a un percorso assoluto. Le variabili d'ambiente già impostate hanno precedenza sul file. Non committare cookie, HAR, database o foto personali. .gitignore include le esclusioni principali ma non impedisce a OneDrive di sincronizzare i file. Vedi SECURITY.md per i confini di fiducia.

Collegamento a ChatGPT

  1. Predisponi un endpoint HTTPS tramite reverse proxy o tunnel verso 127.0.0.1:8000. Non esporre la directory dati.

  2. Nel .env privato imposta MCP_PUBLIC_URL=https://tuo-dominio.example e il segreto.

  3. Avvia uv run vinted-mcp http.

  4. In un ambiente ChatGPT che supporta app MCP personalizzate crea una connessione a https://tuo-dominio.example/mcp con OAuth. Disponibilità e autorizzazioni dipendono dal piano e dalle impostazioni del workspace.

  5. Nella pagina del tuo dominio autorizza il client inserendo MCP_OWNER_SECRET: è il segreto del server, non la password Vinted.

  6. Lascia VINTED_MODE=mock e prova prima foto e conferma simulata.

Il server espone discovery OAuth, registrazione dinamica, PKCE e token vincolati alla risorsa. Non richiede un servizio di autenticazione esterno. I token di accesso durano 24 ore e restano validi ai riavvii. Il refresh token ruota a ogni uso e permette rinnovi per 30 giorni dalla prima autorizzazione; una nuova autorizzazione e necessaria alla scadenza o revoca. Usa un solo worker per i consensi e i codici ancora in corso. Disabilita log di header, corpi e query OAuth nel tunnel/reverse proxy; gli access log dell'app sono disabilitati.

Il widget usa MCP Apps e le estensioni ChatGPT compatibili. Una semplice GPT Action non basta: questa implementazione è un'app MCP con risorsa UI. Il pulsante richiede un host con MCP Apps; con client solo testuali, la conferma va gestita dal client prima di chiamare il tool di scrittura.

Il tool dichiara openai/fileParams e riceve allegati con download_url e file_id, più mime_type e file_name opzionali. Percorsi sandbox:/... non sono scaricabili dal server. Se il client non consegna gli allegati corretti, riassocia le foto. Se usa un altro dominio, aggiungi l'host esatto e fidato a PHOTO_DOWNLOAD_HOSTS, separando gli host con virgole. Non usare wildcard o URL arbitrari.

Riferimenti ufficiali: server MCP, widget MCP Apps, file input e runtime. Connessione e rendering dentro ChatGPT non sono stati verificati in questa sessione.

Configurare un account Vinted normale

Non c'è login con password in questo progetto. Accedi manualmente su Vinted e conserva solo sul tuo PC i cookie di sessione e il token CSRF usato dal sito. Puoi leggerli dagli strumenti sviluppatore nelle richieste del tuo account. Non esportare HAR e non incollarli in chat, issue o file nel repo.

Nel session.json della directory privata, con i valori reali locali:

{
  "cookies": {"nome_cookie_sessione": "VALORE_LOCALE"},
  "csrf_token": "TOKEN_CSRF_LOCALE",
  "anon_id": "OPZIONALE_SE_PRESENTE_NELLA_TUA_SESSIONE"
}

Il nome del cookie è un segnaposto: usa quelli effettivamente richiesti dalla tua sessione. Non tutti i cookie sono necessari. Sessione e CSRF possono scadere e vanno aggiornati manualmente. Una sessione valida nel browser potrebbe essere rifiutata via HTTP. Il server non aggira challenge o autenticazione.

Ogni annuncio è indipendente: categoria, marca, taglia, condizioni e pacco possono cambiare per ogni oggetto. Live richiede la sessione e l'abilitazione esplicita, senza alcun obbligo di creare un profilo salvato.

Facoltativamente puoi creare profiles.json: una lista di combinazioni riutilizzabili per risparmiare inserimenti. I profili non sono una lista di articoli consentiti e non impongono valori agli annunci successivi. ChatGPT può preparare un annuncio con dati diversi da tutti i profili presenti.

Gli ID del singolo annuncio vengono cercati dal server nel modulo Vinted: ChatGPT usa search_listing_categories, poi get_listing_fields e search_listing_brands. search_listing_options permette di cercare taglie, condizioni, colori, pacchi e altri attributi nelle opzioni della categoria scelta. L'utente non deve recuperare ID tecnici né configurare profili per ogni articolo.

Prima del riepilogo, prepare_listing verifica gli ID contro quelle opzioni e usa i nomi restituiti da Vinted. Un ID inventato, una taglia di un'altra categoria o un attributo richiesto mancante fermano la bozza. Le ricerche hanno cache in memoria di 10 minuti e paginazione; in mock usano dati fittizi dichiarati come simulazione. Un errore di ricerca viene segnalato senza inventare valori o chiedere credenziali in chat. Non usare gli ID mock in live. Esempio strutturale di un profilo facoltativo (sostituisci i segnaposto con interi reali):

[
  {
    "name": "Magliette marca X taglia M",
    "catalog_id": "SOSTITUISCI_CON_INTERO",
    "category_label": "Magliette",
    "brand_id": "SOSTITUISCI_CON_INTERO",
    "brand": "MARCA_REALE",
    "status_id": "SOSTITUISCI_CON_INTERO",
    "condition_label": "CONDIZIONE_REALE",
    "size_id": "SOSTITUISCI_CON_INTERO_O_NULL",
    "size_label": "M",
    "package_size_id": "SOSTITUISCI_CON_INTERO",
    "package_label": "Piccolo"
  }
]

Gli attributi aggiuntivi con opzioni numeriche (per esempio materiale o piattaforma) sono trasmessi come item_attributes e mostrati con i rispettivi nomi nel riepilogo. I campi speciali di testo libero non ancora modellati richiedono il modulo Vinted: il server non inventa valori per superare una validazione. Le ricerche usano endpoint web non ufficiali del modulo di vendita e del servizio Vinted di spedizione: la compatibilità con il tuo account resta da verificare. Il contratto sperimentale è basato anche su osservazioni pubbliche del modulo web; non è documentazione ufficiale né una garanzia di accesso.

Per abilitare consapevolmente l'adattatore nel file privato:

VINTED_MODE=live
VINTED_ENABLE_UNOFFICIAL_API=true
VINTED_BASE_URL=https://www.vinted.it

Riavvia e crea nuove bozze: una bozza mock non può essere pubblicata live. Le ricerche leggono categorie, marche, attributi e formati del pacco. Preparare il riepilogo può leggere/validare quei metadati ma non carica foto, crea bozze remote o pubblica. Dopo la conferma partono upload foto, bozza remota e completamento. Un completamento fallito può lasciare una bozza remota: controlla dal sito.

La libreria suggerita ha una release 0.3.9 del luglio 2025 e descrive soprattutto lettura di cataloghi e prodotti. Non è una dipendenza perché non stabilisce un contratto ufficiale per questo flusso di scrittura. L'adattatore separato permette di passare a un'API autorizzata in futuro.

Errori e doppi invii

  • Le bozze scadono dopo 30 minuti; ogni modifica richiede nuova bozza e conferma.

  • SQLite registra l'inizio dell'invio prima delle richieste di rete.

  • Dopo un successo, un doppio clic restituisce l'esito senza ripubblicare.

  • Timeout, crash e risposte inattese richiedono verifica manuale, senza retry automatici.

  • Per default gli errori non impongono un blocco globale persistente: fallisce solo l'operazione corrente. VINTED_AUTO_SUSPEND=true riabilita facoltativamente il blocco globale.

  • Dopo aver controllato account, bozze e annunci: uv run vinted-mcp unblock. Le bozze già tentate restano non reinviabili; creane un'altra solo dopo aver verificato che non esista già un annuncio.

  • Almeno 60 secondi fra tentativi live. È un limite locale, non una soglia dichiarata sicura da Vinted né una garanzia contro i ban.

Sviluppo

uv sync --extra dev --locked
uv run pytest -q
uv run ruff check .
uv pip check

I test coprono OAuth/PKCE e accesso HTTP, contratto MCP e allegati, persistenza, concorrenza, duplicati, scadenza, isolamento mock/live, rifiuti API, host non fidati e rimozione EXIF. Il contratto Vinted usa risposte simulate: i test non dimostrano compatibilità con il servizio reale.

server.py espone MCP/UI; auth.py gestisce l'accesso personale; service.py orchestra l'invio; storage.py conserva stati; photos.py importa gli allegati; vinted.py contiene l'adattatore di pubblicazione; metadata.py gestisce le opzioni del modulo per il singolo oggetto. La CI usa dati sintetici senza credenziali Vinted o OpenAI.

Non sono stati pubblicati repository, plugin, siti o annunci durante lo sviluppo.

Rinnovo della sessione Vinted e limiti locali

Il server rinnova automaticamente i cookie con il normale endpoint Vinted POST /web/api/auth/refresh quando l'access token sta scadendo. Il refresh e serializzato tra processi e salva atomicamente i cookie ruotati nel file privato. Una ricerca di metadati che riceve 401 puo essere ripetuta una sola volta dopo un refresh riuscito. Le operazioni di pubblicazione non vengono ripetute alla cieca.

Il rinnovo richiede un refresh token ancora valido e accettato da Vinted. Non aggira CAPTCHA, verifiche aggiuntive, 403 o 429. Una sessione copiata dal browser puo essere revocata se il browser e il server consumano separatamente lo stesso refresh token: per uso continuativo preferire una sessione dedicata al server. Non occorre fornire la password Vinted all'assistente quando il refresh funziona.

Il comando vinted-mcp refresh-session permette un rinnovo esplicito dal terminale, senza stampare credenziali. Impostare VINTED_ENV_FILE come per il servizio.

Per default VINTED_AUTO_SUSPEND=false e VINTED_PUBLISH_COOLDOWN_SECONDS=0: nessuna sospensione globale automatica o attesa fissa di 60 secondi. Restano la conferma dell'annuncio e la protezione contro doppi invii o esiti incerti.

Mantenimento Vinted in background

L'installer abilita vinted-mcp-session.timer, che controlla la sessione ogni 5 minuti, anche senza richieste da ChatGPT, e la rinnova quando restano al massimo 15 minuti. Il timer e persistente e riparte dopo un riavvio del server. vinted-mcp maintain-session esegue lo stesso controllo una sola volta, senza forzare un rinnovo non necessario.

Per evitare conflitti di rotazione, inizializzare una sessione dedicata: aprire una finestra privata del browser, accedere a Vinted e importare Cookie/CSRF con il wizard. Poi chiudere la finestra senza eseguire Logout e non riutilizzare quella sessione nel browser. Le altre sessioni indipendenti del proprio account possono restare separate.

Un refresh token rifiutato con 400/401 viene riconosciuto tramite hash e non viene ripresentato a ogni esecuzione del timer. Serve una nuova autenticazione se Vinted lo invalida; il timer riprende automaticamente quando il wizard salva la nuova sessione. Non viene salvata la password dell'account.

sudo systemctl list-timers vinted-mcp-session.timer
sudo journalctl -u vinted-mcp-session.service -n 20 --no-pager

Available Tools

6 tools
get_listingB
Read-only

Read exact listing summary and publication status without contacting Vinted.

Inputs: draft_id (required).

get_listing_profilesA
Read-only

Read verified category/brand/condition/size/package IDs and labels from local configuration. Mock IDs are only for simulation. Never guess real IDs or unverified item characteristics.

Inputs: no named parameters. Returns: object

get_statusB
Read-only

Return mode and session file presence, never credentials.

Inputs: no named parameters. Returns: object

import_photosA

Download 1–20 user-provided ChatGPT photo attachments and save locally without EXIF/GPS. Requires actual file objects from ChatGPT, never sandbox paths or invented URLs.

Inputs: photos (required). Returns: object

prepare_listingA

Save an immutable listing for 30 minutes and show summary and confirmation button. Does not contact Vinted. Any edits require a new draft and renewed confirmation.

Inputs: listing (required).

publish_listingA
DestructiveIdempotent

Publish the exact reviewed draft ONLY after the user's confirmation button click. External write; never call proactively. Repeated successful calls return the saved result.

Inputs: draft_id (required). Returns: object

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 6 tools

    Disambiguation4/5

    The lifecycle actions (import_photos, prepare_listing, publish_listing, get_listing) are clearly distinct in purpose and readable. The only mild overlap is between get_status and get_listing_profiles, which both read local state/config, though their descriptions differentiate them well enough.

    Naming Consistency5/5

    All six tools follow a consistent snake_case verb_noun pattern (get_status, get_listing_profiles, import_photos, get_listing, prepare_listing, publish_listing), with no mixed conventions or vague verbs.

    Tool Count5/5

    Six tools map cleanly onto a focused create-and-publish workflow, each earning its place with a distinct step. The surface is well-scoped for the narrow purpose.

    Completeness4/5

    The core lifecycle (read config, import photos, prepare immutable draft, publish, inspect listing/status) is covered with sensible safety gates. Minor gaps exist — no cancel/withdraw of a prepared draft and no way to list existing listings — but these are workable around the immutable-draft design.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      A
      quality
      D
      maintenance
      An MCP server that automates Xianyu marketplace operations through Playwright, allowing users to manage listings and conduct market research via natural language. It features integrated tools for generating AI-powered product descriptions and cover images using DashScope.
      11
      24
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      A self-hosted MCP server that gives ChatGPT a secure connection to your local machine, enabling it to read, edit, search, and run code in your projects.
      693 npm
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      An MCP server that helps sellers create Vinted listings from photos, researching comparable listings, estimating prices, and filling the listing form. It requires explicit confirmation before publishing, deleting, or sending messages.
      27
      MIT