mareply-mcp
v0.4.0
Published
Server MCP di Mareply: pubblica un contenuto Instagram, con o senza automazione ai commenti, da Claude Code.
Maintainers
Readme
mareply-mcp
Server MCP di Mareply. Gira sul computer di chi lo usa, legge dal disco i file da pubblicare — una foto, un reel o un carosello — e li porta su Instagram passando da Mareply: caricamento, automazione, programmazione.
Perché gira in locale
Il file da pubblicare sta sul disco di chi scrive il post. Un server remoto non lo vede, e mandare un reel da 50 MB dentro i parametri di un tool non è praticabile: perciò questo pacchetto viene avviato da Claude Code sulla macchina dell'utente, legge il file, lo converte se serve e ne carica i byte su Mareply con una chiave API.
Requisiti
- Node 20 o superiore
ffmpegeffprobenelPATH(brew install ffmpeg,apt install ffmpeg)- una chiave API di Mareply: Impostazioni → Accesso programmatico
Configurazione
claude mcp add mareply \
--env MAREPLY_API_KEY=mrp_la_tua_chiave \
--env MAREPLY_BASE_URL=https://il-tuo-dominio \
-- npx -y mareply-mcpMAREPLY_BASE_URL è l'indirizzo della propria installazione Mareply e non ha un valore predefinito: Mareply si installa per cliente, e un default sbagliato manderebbe la chiave — e il post — all'host di qualcun altro.
Deve essere https, tranne su localhost.
Per collegarlo a un solo progetto invece che a tutto il computer, un .mcp.json nella cartella del progetto:
{
"mcpServers": {
"mareply": {
"command": "npx",
"args": ["-y", "mareply-mcp"],
"env": {
"MAREPLY_API_KEY": "mrp_la_tua_chiave",
"MAREPLY_BASE_URL": "https://il-tuo-dominio"
}
}
}
}La chiave resta scritta nel file: se il progetto è su Git, tienilo fuori dal repository.
Verificare che sia collegato
Chiedere a Claude Code: «elenca i miei account Instagram su Mareply».
Una risposta con il proprio @ significa che il collegamento funziona; «Nessun account collegato» significa che funziona lo stesso ed è Mareply a non averne ancora uno.
Se qualcosa non va
| Messaggio | Cosa fare |
| --- | --- |
| MAREPLY_API_KEY non è impostata | Il server è partito senza chiave: controlla che nel comando ci sia quella vera e che inizi per mrp_. |
| Chiave API non valida o revocata | La chiave non esiste più, o è stata copiata a metà. Creane un'altra: non si recuperano, si vedono una volta sola. |
| Serve ffmpeg per leggere e convertire i file | Manca ffmpeg. brew install ffmpeg o apt install ffmpeg, poi riavvia Claude Code. |
| Ci sono N account collegati: indica quale | Con più account il server non indovina: basta dire «pubblica su @nome». |
| L'orario di pubblicazione deve essere nel futuro | L'orario è sempre italiano, anche se il computer è su un altro fuso. |
| Un carosello accetta solo immagini, e X è un video | Un reel si pubblica da solo: togli il video dall'elenco, oppure fanne un post a parte. |
| Un carosello accetta al massimo 10 immagini | Il limite è di Instagram. Con undici file, il post va spezzato in due. |
Gli strumenti
| Strumento | Cosa fa |
| --- | --- |
| mareply_list_accounts | Gli account Instagram collegati. Serve quando ce n'è più di uno. |
| mareply_list_automations | Le automazioni esistenti, con keyword, DM, cosa chiedono e a quali post rispondono. |
| mareply_list_posts | Gli ultimi contenuti con il loro stato. |
| mareply_publish_content | L'unica scrittura: carica i file, se richiesta crea o collega l'automazione, pubblica o programma. |
mareply_publish_content
files uno o più percorsi sul disco: uno solo è un post,
da 2 a 10 immagini sono un carosello nell'ordine indicato
caption massimo 2200 caratteri
when "subito" oppure "2026-08-20 18:30" (orario italiano, sempre)
accountId obbligatorio solo con più di un account collegato
automationId facoltativo: collega un'automazione esistente…
automation …oppure creane una nuova: nome, keywords, dmMessage,
resources (max 3), customVars, linkDelivery,
publicReplies (max 4), followMode, wholeWordMatch.
Ometti entrambi per pubblicare il post e basta,
senza risposta automatica ai commenti
fit auto | fit | fill — come riquadrare un'immagine fuori formato
shareToFeed predefinito true
confirm il token dell'anteprima, solo per pubblicare subitoI valori predefiniti sono quelli dell'app: risposta pubblica attiva con quattro messaggi estratti a caso uno per commento, obbligo di seguire attivo, corrispondenza a parola intera. Il contenuto non viene mai dichiarato come generato dall'AI: questo server non sa se il file che riceve lo sia.
Pubblicare un'immagine
Un solo file, e il tipo lo deduce il server:
«pubblica su Instagram ~/foto/lancio.jpg con la caption … e un'automazione sulla keyword GUIDA»
L'immagine diventa un JPEG dentro 4:5–1.91:1, al massimo 1440 px sul lato lungo. Un file che già rispetta tutte e tre le condizioni viene caricato intatto: un secondo passaggio JPEG costa qualità e non serve a niente.
La riquadratura è il punto che sorprende, perché l'app di Instagram accetta il 3:4 e l'API di pubblicazione no — e il 3:4 è quello che scatta ogni telefono moderno.
auto ritaglia quando il taglio è minimo (≤10%: una foto 3:4 ne perde il 6,25%) e mette bande bianche quando la perdita è reale.
fit: "fit" mette sempre le bande, fit: "fill" ritaglia sempre.
L'anteprima dice cosa è successo prima che venga caricato qualsiasi cosa.
Pubblicare un reel
Sempre un file solo, ma un video:
«programma ~/video/glm-vs-claude.mp4 per domani alle 18:30, caption … , keyword ABC123»
Il video non viene mai ricodificato.
Un contenitore che Instagram non accetta viene rimuxato con -c copy, quindi le tracce restano identiche; un codec che non passa produce un errore con il comando ffmpeg da eseguire, non una riconversione silenziosa di 200 MB decisa al posto tuo.
shareToFeed è true di default: il reel appare anche nel feed.
Dopo la pubblicazione il post resta PROCESSING finché Instagram non ha finito di transcodificare — su un file lungo sono minuti, non secondi.
Non è un errore e non consuma tentativi: il lavoro si ri-accoda da solo e mareply_list_posts mostra quando diventa PUBLISHED, con il link.
Pubblicare un carosello
Basta indicare più file, nell'ordine in cui devono apparire:
«pubblica su Instagram queste tre immagini come carosello: ~/foto/1.jpg, ~/foto/2.jpg, ~/foto/3.jpg, con la caption … e l'automazione sulla keyword GUIDA»
Da 2 a 10 immagini, il limite è di Instagram. Un carosello accetta solo immagini: se tra i file c'è un video il server rifiuta prima di convertire e caricare qualsiasi cosa, perché un reel è un contenuto a sé.
Tutte le immagini vengono riquadrate nel formato della prima.
Instagram rifiuta un carosello le cui immagini non hanno la stessa proporzione, e una striscia che cambia forma mentre si scorre sembra rotta anche quando viene pubblicata.
Quindi la prima immagine decide il formato — 4:5, quadrato, orizzontale, quello che è, purché dentro 4:5–1.91:1 — e le altre ci vengono disegnate dentro con le stesse regole di fit/fill di sempre.
L'anteprima mostra riga per riga cosa succede a ciascuna, così si vede subito quale delle dieci è quella che viene tagliata:
File: Carosello di 3 immagini, tutte nel formato della prima
1. 1.jpg · 1080×1350, nessuna modifica
2. 2.jpg · 1080×1080 → 864×1080, con bande bianche sul 20%
3. 3.jpg · 1600×900 → 720×900, con bande bianche sul 55%Se la seconda immagine non deve avere le bande bianche, fit: "fill" la ritaglia — la scelta vale per tutto il post, non per una sola immagine.
Per cambiare formato al carosello si cambia l'ordine dei file: comanda il primo.
Pubblicare subito richiede due chiamate
Un post programmato si annulla, uno già su Instagram no.
Quindi con when: "subito" la prima chiamata restituisce un'anteprima — account, caption, media, automazione — e un token; solo una seconda chiamata che porta quel token in confirm pubblica davvero.
Il token vale dieci minuti e una volta sola.
Programmare resta una chiamata sola: c'è tutta una finestra per cambiare idea.
Cosa succede al file
- Reel: caricato senza toccarlo. Un contenitore che Instagram non accetta viene rimuxato con
-c copy(le tracce restano identiche); un codec che non passa produce un errore con il comando da eseguire, non una riconversione silenziosa. - Immagini: JPEG dentro 4:5–1.91:1, al massimo 1440 px sul lato lungo. Un file che già rispetta tutto viene caricato così com'è — un secondo passaggio JPEG costa qualità e non serve a niente.
- Riquadratura:
autoritaglia quando il taglio è minimo (≤10%, per esempio una foto 3:4 che ne perde il 6,25%) e mette bande bianche quando la perdita è reale. Sono le stesse regole diprepareImageForUploadnell'app. - Carosello: ogni immagine viene disegnata nel formato della prima, non nel proprio. Un'immagine già a posto da sola viene comunque riconvertita se la sua forma non è quella del carosello, perché è esattamente il file che Instagram rifiuta.
Il tipo di contenuto è dedotto dal file, e non dalla durata: il demuxer image2 assegna a un JPEG una durata fittizia di 0,04 secondi, quindi la classificazione legge il contenitore.
Sviluppo
npm install
npm test # tsc + vitest: conversioni con ffmpeg vero, e il server via JSON-RPC su stdio
npm run buildI test end-to-end avviano dist/index.js come processo separato e gli parlano come farebbe Claude Code, con l'API di Mareply simulata.
Sono quelli che hanno trovato l'unico bug serio di questo pacchetto: un JPEG caricato come video/mp4.
