Scheduler de publication MCP pour Twitter
Ceci est unMiscellaneous, AI RAG, Multimodal AIworkflow d'automatisation du domainecontenant 16 nœuds.Utilise principalement des nœuds comme Code, Wait, MySql, Slack, Twitter. Analyse des tendances et publication automatisée de contenu Twitter avec OpenAI GPT et MCP
- •Informations de connexion à la base de données MySQL
- •Token Bot Slack ou URL Webhook
- •Informations d'identification Twitter API
- •Clé API OpenAI
Nœuds utilisés (16)
Catégorie
{
"id": "8BcTtr8AdLgBa23S",
"meta": {
"instanceId": "9c51453afbec31d8209fd304a1a3e6af1fb4621ca939ac8364a6b6d4aeed48c1",
"templateCredsSetupCompleted": true
},
"name": "twitter_mcp_post_scheduler",
"tags": [],
"nodes": [
{
"id": "dd350044-eff4-40b7-bbe8-aaf95d17e019",
"name": "Formater les résultats 1",
"type": "n8n-nodes-base.function",
"position": [
720,
-128
],
"parameters": {
"functionCode": "// Get the raw array of names from the AI Agent\nlet arr = items[0].json.output;\n\n// If it's a stringified array, parse it\nif (typeof arr === 'string') {\n arr = JSON.parse(arr);\n}\n\n// Ensure it's an array\nif (!Array.isArray(arr)) {\n return [];\n}\n\n// Return one item per trend name\nreturn arr.map(name => ({ json: { name } }));\n"
},
"typeVersion": 1
},
{
"id": "b60238c7-03b5-4a5b-84ca-c01e2cd3af93",
"name": "Boucler sur les éléments",
"type": "n8n-nodes-base.splitInBatches",
"position": [
896,
144
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "deb12dad-4c08-4310-8dd2-46c1615eaaed",
"name": "Agent IA",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1184,
-112
],
"parameters": {
"text": "=You are an AI agent with access to ONE MCP server:\n- Twitter Search → aigeon-ai-twitter154.search_tweets\n\nINPUT (from workflow)\nTrend name: {{ $json.name }}\n\nGoal\nSearch recent tweets for the given trend name and produce a concise, brand-safe “why it’s trending” summary. Do not generate or request any images.\n\nRules\n- Make at most ONE tool call.\n- Use the INPUT trend name verbatim as the query (no expansions).\n- Focus on “why now” (current event, game, release, announcement, controversy, etc.).\n- Keep it readable for a general audience; no hashtags, emojis, or @usernames.\n- Include concrete details if available; do NOT fabricate.\n- If the input is empty after trimming, skip the tool call and return the JSON with a brief “unknown reason” summary.\n\nSteps\n1) CALL `aigeon-ai-twitter154.search_tweets` with the trend name as the query (recent timeframe).\n2) Synthesize a 1–2 sentence summary (≈30–60 words) explaining why it’s trending.\n\nOutput (STRICT)\nReturn ONLY this JSON object (no prose, no extra keys, no markdown fences):\n\n{\n \"trend\": \"{{ $json.name }}\",\n \"summary\": \"<your concise explanation in 30–60 words>\",\n \"search_url\": \"https://x.com/search?q={{ encodeURIComponent($json.name) }}\",\n \"image_url\": null,\n \"image_prompt\": null,\n \"aspect_ratio\": \"16:9\"\n}\n",
"options": {},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "2dff454b-a58a-4303-9e5b-dafd635250a7",
"name": "Client MCP",
"type": "@n8n/n8n-nodes-langchain.mcpClientTool",
"position": [
1328,
304
],
"parameters": {
"endpointUrl": "https://amber.mcpreview.com/slug/aigeon-ai-twitter154",
"authentication": "headerAuth",
"serverTransport": "httpStreamable"
},
"credentials": {
"httpHeaderAuth": {
"id": "DNAG7Ji5OdnS7oBi",
"name": "Header Auth account"
}
},
"typeVersion": 1.1
},
{
"id": "862a8930-0f27-4e51-b662-c28b9240c5f7",
"name": "Envoyer un message",
"type": "n8n-nodes-base.slack",
"position": [
1680,
-112
],
"webhookId": "ae669a44-f283-42b3-9cea-6f0b0febe4da",
"parameters": {
"text": "={{ $json.output }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "name",
"value": "#mcp-hub-test"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"id": "CbAz3Qd1iNJhMuNj",
"name": "Slack account"
}
},
"typeVersion": 2.3
},
{
"id": "427bb5ba-2ba0-4444-89ab-4488b3e874ce",
"name": "Attendre",
"type": "n8n-nodes-base.wait",
"position": [
2640,
304
],
"webhookId": "adf20b2f-acdc-49b1-96c5-7c57a18ea1cd",
"parameters": {},
"typeVersion": 1.1
},
{
"id": "baa30922-1058-41d7-a394-cd1f1a9fb48a",
"name": "OpenAI Modèle de chat",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1184,
288
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-5-mini",
"cachedResultName": "gpt-5-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "Kca9177CPSlzNiHg",
"name": "Cooper Openai"
}
},
"typeVersion": 1.2
},
{
"id": "bf43e456-b478-4038-a1b4-f2b05dddc5c6",
"name": "Prétraitement d'agent IA",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
208,
-128
],
"parameters": {
"text": "=You are an AI agent with access to ONE MCP server:\n- Twitter trends → get-trends-near-location\n\nINPUT from workflow\nEXCLUDE (JSON array of normalized forms): {{ JSON.stringify($json.exclude || []) }}\n\nPrimary goal\nReturn the most conversation-worthy U.S. trend. Cross-run suppression is handled in MySQL, but you must also avoid any trend whose normalized form appears in EXCLUDE.\n\nTask\n1) CALL `get-trends-near-location` with WOEID 23424977 (United States). The tool may return an array of items like:\n { name, url, query, tweet_volume|null, ... }. Handle missing fields gracefully.\n\n2) Internally normalize names for comparison ONLY:\n • lowercase • strip leading “#” • trim • collapse spaces • remove surrounding punctuation/symbols\n\n3) Filter out any item whose normalized form is present in EXCLUDE.\n\n4) Score remaining items by ENGAGEMENT POTENTIAL (not just tweet volume). Treat tweet_volume=null as UNKNOWN (do NOT treat as 0). Prefer:\n • clear moments happening now (games, finals, premieres, elections, announcements, releases, controversies, breaking news)\n • specific & recognizable entities over generic tags\n • conversation-friendly, broad-interest communities\n • distinct items (avoid near-duplicates)\n • brand-safe topics (skip NSFW/harassment)\n\n Heuristics (guidance, not rules):\n • +3 specific event/entity signals (e.g., “Team A vs Team B”, “Finale”, “Kickoff”, “Trailer”, “Album”, “Box Office”)\n • +2 strong recognizability (proper-noun phrases, league/team/celebrity names)\n • +1 recency cues in top tweets (today/tonight/just announced) if visible via the search URL/metadata\n • TIE-BREAKERS ONLY: when two candidates are otherwise close, prefer the one with a non-null tweet_volume; if both have volume, prefer the higher.\n\n Exclude/penalize:\n • overly generic tags (#news, #breaking), single emojis, day-of-week only, spammy promos.\n\n5) Select exactly ONE trend name with the highest overall score.\n • If no viable item remains, return an empty list. Do NOT fabricate.\n\nOutput (STRICT)\nReturn ONLY a JSON array of strings with the final human-friendly name(s). No prose, counts, or extra fields.\nExample: [\"Cracker Barrel\"]\n",
"options": {},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "45a35c06-c201-40a4-a058-c864afc3e8fb",
"name": "OpenAI Modèle de chat 1",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
176,
128
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini",
"cachedResultName": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "Kca9177CPSlzNiHg",
"name": "Cooper Openai"
}
},
"typeVersion": 1.2
},
{
"id": "5715d5af-7b63-4e92-99a8-b0a87a2b3dcf",
"name": "Client MCP 1",
"type": "@n8n/n8n-nodes-langchain.mcpClientTool",
"position": [
352,
144
],
"parameters": {
"endpointUrl": "https://amber.mcpreview.com/slug/aigeon-ai-twitter154",
"authentication": "headerAuth",
"serverTransport": "httpStreamable"
},
"credentials": {
"httpHeaderAuth": {
"id": "DNAG7Ji5OdnS7oBi",
"name": "Header Auth account"
}
},
"typeVersion": 1.1
},
{
"id": "c40a0864-3376-43db-bc02-46e3069e33a2",
"name": "Exécuter une requête SQL",
"type": "n8n-nodes-base.mySql",
"position": [
2144,
-272
],
"parameters": {
"query": "INSERT INTO keyword_registry\n (platform, locale, raw_keyword, canon, status, published_at, publish_payload, next_eligible_at)\nVALUES (\n $1, -- platform\n $2, -- locale\n $3, -- raw_keyword (trend)\n $4, -- canon\n 'published',\n NOW(),\n JSON_OBJECT(\n 'trend', $3,\n 'summary', $5,\n 'search_url', $6,\n 'image_url', NULL,\n 'image_prompt', NULL,\n 'aspect_ratio', COALESCE($7, '16:9'),\n 'slack', JSON_OBJECT(\n 'channel', $8,\n 'ts', $9,\n 'message_timestamp', $10\n )\n ),\n DATE_ADD(NOW(), INTERVAL 3 DAY)\n)\nON DUPLICATE KEY UPDATE\n last_seen = CURRENT_TIMESTAMP,\n status = 'published',\n published_at = NOW(),\n publish_payload = VALUES(publish_payload),\n next_eligible_at = DATE_ADD(NOW(), INTERVAL 3 DAY);\n",
"options": {
"queryReplacement": "={{ [\n $json.platform || 'twitter', // $1\n $json.locale || 'US', // $2\n $json.trend,\n ($json.canon ??\n String($json.trend || '')\n .normalize('NFKC')\n .toLowerCase()\n .replace(/^#+/, '')\n .replace(/\\s+/g, ' ')\n .trim()\n ), // $4 (canon)\n $json.summary, // $5\n $json.search_url, // $6\n $json.aspect_ratio || '16:9', // $7\n ($json.channel ?? $json.message?.channel), // $8\n ($json.message?.ts ?? $json.ts ?? null), // $9\n ($json.message_timestamp ?? null) // $10\n] }}\n"
},
"operation": "executeQuery"
},
"credentials": {
"mySql": {
"id": "kqvrRLnX254pfQhm",
"name": "MySQL account"
}
},
"typeVersion": 2.5
},
{
"id": "9209ade7-5c70-452d-a832-9770a0691038",
"name": "Exécuter une requête SQL 1",
"type": "n8n-nodes-base.mySql",
"position": [
-48,
-112
],
"parameters": {
"query": "SELECT\n CAST(CONCAT(\n '[',\n IFNULL(GROUP_CONCAT(JSON_QUOTE(canon)\n ORDER BY published_at DESC\n SEPARATOR ','), ''),\n ']'\n ) AS JSON) AS exclude\nFROM (\n SELECT canon, published_at\n FROM keyword_registry\n WHERE platform = $1\n AND locale = $2\n AND status = 'published'\n AND next_eligible_at > NOW() -- still in the 3-day window\n ORDER BY published_at DESC\n LIMIT 30\n) AS t;\n",
"options": {
"queryReplacement": "={{ [ 'twitter', 'US' ] }}"
},
"operation": "executeQuery"
},
"credentials": {
"mySql": {
"id": "kqvrRLnX254pfQhm",
"name": "MySQL account"
}
},
"typeVersion": 2.5
},
{
"id": "b891d9e0-1501-46b2-8a5f-17997b65eae6",
"name": "Déclencheur planifié",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-352,
-128
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 2,
"triggerAtMinute": 12
}
]
}
},
"typeVersion": 1.2
},
{
"id": "bd1341ee-dcd6-45cb-9b43-f986be70634f",
"name": "Attendre 1",
"type": "n8n-nodes-base.wait",
"position": [
2080,
-736
],
"webhookId": "0c0a6cd3-b2cd-4ea7-85ba-3b38f901c572",
"parameters": {},
"typeVersion": 1.1
},
{
"id": "903b774d-3b3a-4a24-b3fb-ae1e5a668f13",
"name": "Créer un Tweet",
"type": "n8n-nodes-base.twitter",
"position": [
2864,
-192
],
"parameters": {
"text": "={{ $json.trend }}: {{ $json.summary }}",
"additionalFields": {}
},
"credentials": {
"twitterOAuth2Api": {
"id": "X7FXukmqV03ghtzN",
"name": "X account Ella.m@newsbreak.com"
}
},
"typeVersion": 2
},
{
"id": "d8411ea5-95c6-4c76-8af8-f35d279c84cb",
"name": "Formateur de mots-clés",
"type": "n8n-nodes-base.code",
"position": [
1504,
-480
],
"parameters": {
"jsCode": "let o = $json.output;\nif (typeof o === 'string') {\n try { o = JSON.parse(o); } catch { o = {}; }\n}\nconst trend = o.trend ?? '';\nconst canon = trend\n .normalize('NFKC')\n .toLowerCase()\n .replace(/^#+/,'')\n .replace(/\\s+/g,' ')\n .trim();\n\nreturn [{\n json: {\n platform: 'twitter',\n locale: 'US',\n ...o, // trend, summary, search_url, etc.\n canon\n }\n}];\n"
},
"typeVersion": 2
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "f87d8268-70b1-4e5b-9111-c280b354b3b8",
"connections": {
"427bb5ba-2ba0-4444-89ab-4488b3e874ce": {
"main": [
[]
]
},
"bd1341ee-dcd6-45cb-9b43-f986be70634f": {
"main": [
[
{
"node": "903b774d-3b3a-4a24-b3fb-ae1e5a668f13",
"type": "main",
"index": 0
}
]
]
},
"deb12dad-4c08-4310-8dd2-46c1615eaaed": {
"main": [
[
{
"node": "862a8930-0f27-4e51-b662-c28b9240c5f7",
"type": "main",
"index": 0
},
{
"node": "d8411ea5-95c6-4c76-8af8-f35d279c84cb",
"type": "main",
"index": 0
}
]
]
},
"2dff454b-a58a-4303-9e5b-dafd635250a7": {
"ai_tool": [
[
{
"node": "deb12dad-4c08-4310-8dd2-46c1615eaaed",
"type": "ai_tool",
"index": 0
}
]
]
},
"5715d5af-7b63-4e92-99a8-b0a87a2b3dcf": {
"ai_tool": [
[
{
"node": "bf43e456-b478-4038-a1b4-f2b05dddc5c6",
"type": "ai_tool",
"index": 0
}
]
]
},
"903b774d-3b3a-4a24-b3fb-ae1e5a668f13": {
"main": [
[
{
"node": "427bb5ba-2ba0-4444-89ab-4488b3e874ce",
"type": "main",
"index": 0
}
]
]
},
"862a8930-0f27-4e51-b662-c28b9240c5f7": {
"main": [
[
{
"node": "427bb5ba-2ba0-4444-89ab-4488b3e874ce",
"type": "main",
"index": 0
}
]
]
},
"dd350044-eff4-40b7-bbe8-aaf95d17e019": {
"main": [
[
{
"node": "b60238c7-03b5-4a5b-84ca-c01e2cd3af93",
"type": "main",
"index": 0
}
]
]
},
"b60238c7-03b5-4a5b-84ca-c01e2cd3af93": {
"main": [
[],
[
{
"node": "deb12dad-4c08-4310-8dd2-46c1615eaaed",
"type": "main",
"index": 0
}
]
]
},
"b891d9e0-1501-46b2-8a5f-17997b65eae6": {
"main": [
[
{
"node": "9209ade7-5c70-452d-a832-9770a0691038",
"type": "main",
"index": 0
}
]
]
},
"baa30922-1058-41d7-a394-cd1f1a9fb48a": {
"ai_languageModel": [
[
{
"node": "deb12dad-4c08-4310-8dd2-46c1615eaaed",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"d8411ea5-95c6-4c76-8af8-f35d279c84cb": {
"main": [
[
{
"node": "bd1341ee-dcd6-45cb-9b43-f986be70634f",
"type": "main",
"index": 0
},
{
"node": "c40a0864-3376-43db-bc02-46e3069e33a2",
"type": "main",
"index": 0
}
]
]
},
"45a35c06-c201-40a4-a058-c864afc3e8fb": {
"ai_languageModel": [
[
{
"node": "bf43e456-b478-4038-a1b4-f2b05dddc5c6",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"bf43e456-b478-4038-a1b4-f2b05dddc5c6": {
"main": [
[
{
"node": "dd350044-eff4-40b7-bbe8-aaf95d17e019",
"type": "main",
"index": 0
}
]
]
},
"c40a0864-3376-43db-bc02-46e3069e33a2": {
"main": [
[
{
"node": "427bb5ba-2ba0-4444-89ab-4488b3e874ce",
"type": "main",
"index": 0
}
]
]
},
"9209ade7-5c70-452d-a832-9770a0691038": {
"main": [
[
{
"node": "bf43e456-b478-4038-a1b4-f2b05dddc5c6",
"type": "main",
"index": 0
}
]
]
}
}
}Comment utiliser ce workflow ?
Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.
Dans quelles scénarios ce workflow est-il adapté ?
Avancé - Divers, RAG IA, IA Multimodale
Est-ce payant ?
Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.
Workflows recommandés
Partager ce workflow