Twitter MCPによる投稿スケジューラー
上級
これはMiscellaneous, AI RAG, Multimodal AI分野の自動化ワークフローで、16個のノードを含みます。主にCode, Wait, MySql, Slack, Twitterなどのノードを使用。 OpenAI GPT と MCP を使ってトレンド分析し、Twitter コンテンツ公開を自動化
前提条件
- •MySQLデータベース接続情報
- •Slack Bot Token または Webhook URL
- •Twitter API認証情報
- •OpenAI API Key
使用ノード (16)
ワークフロープレビュー
ノード接続関係を可視化、ズームとパンをサポート
ワークフローをエクスポート
以下のJSON設定をn8nにインポートして、このワークフローを使用できます
{
"id": "8BcTtr8AdLgBa23S",
"meta": {
"instanceId": "9c51453afbec31d8209fd304a1a3e6af1fb4621ca939ac8364a6b6d4aeed48c1",
"templateCredsSetupCompleted": true
},
"name": "twitter_mcp_post_scheduler",
"tags": [],
"nodes": [
{
"id": "dd350044-eff4-40b7-bbe8-aaf95d17e019",
"name": "結果のフォーマット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": "アイテムのループ処理",
"type": "n8n-nodes-base.splitInBatches",
"position": [
896,
144
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "deb12dad-4c08-4310-8dd2-46c1615eaaed",
"name": "AIエージェント",
"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": "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": "メッセージ送信",
"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": "待機",
"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チャットモデル",
"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": "AIエージェント前処理",
"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チャットモデル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": "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": "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": "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": "スケジュールトリガー",
"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": "待機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": "ツイート作成",
"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": "キーワードフォーマッター",
"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
}
]
]
}
}
}よくある質問
このワークフローの使い方は?
上記のJSON設定コードをコピーし、n8nインスタンスで新しいワークフローを作成して「JSONからインポート」を選択、設定を貼り付けて認証情報を必要に応じて変更してください。
このワークフローはどんな場面に適していますか?
上級 - その他, AI RAG検索拡張, マルチモーダルAI
有料ですか?
このワークフローは完全無料です。ただし、ワークフローで使用するサードパーティサービス(OpenAI APIなど)は別途料金が発生する場合があります。
関連ワークフロー
GPT-4、GoogleSearchAPI、Slackを使ったニュース発見と公開の自動化
GPT-4、Google検索API、Slackを使ってニュース発見と公開の自動化
Code
Slack
Http Request
+
Code
Slack
Http Request
14 ノードKalyxi Ai
その他
WordPress の記事
Google Trends、GPT-4、Pexels、WordPressを基にした自動ブログ公開
Set
Xml
Code
+
Set
Xml
Code
20 ノードCojocaru David
コンテンツ作成
毎日の WhatsApp グループ スマート分析:GPT-4.1 による分析と音声メッセージの transcrição
毎日の WhatsApp グループ インタラクティブ分析:GPT-4.1 分析と音声メッセージ文字起こし
If
Set
Code
+
If
Set
Code
52 ノードDaniel Lianes
その他
n8nノードの探索(可視化リファレンスライブラリ内)
n8nノードを可視化リファレンスライブラリで探索
If
Ftp
Set
+
If
Ftp
Set
113 ノードI versus AI
その他
💥 VEO 3を使ってAIウイルス動画を生成してTikTokにアップロード
VEO 3でAIウイルスビデオを生成し、TikTokにアップロード
Set
Code
Wait
+
Set
Code
Wait
24 ノードDr. Firas
コンテンツ作成
コンテキスト・ハイブリッドRAG AIコピー
RAGアプリケーション向けのGoogle DriveからSupabaseコンテキストベクトルデータベースへの同期
If
Set
Code
+
If
Set
Code
76 ノードMichael Taleb
AI RAG検索拡張