※「ChatGPTと育てる、自分専用AI基盤」第5回です。
前回は、ChatGPTがコードを変更できるようになっても、その変更をそのままmainへ入れず、GitHub Pull Requestを「正式に採用する境界」にした話を書きました。
→ 第4回:ChatGPTからPRを作り、安全にマージできるようにした
ここまでで、記憶、開発、強い実行、GitHubでの確定まで、かなりの作業をChatGPTから進められるようになりました。
すると次に気になったのは、ブログとSNSです。
ChatGPTに記事を書いてもらうこと自体は、かなり前からできていました。
でも、記事を書いてもらっただけでは公開されません。
WordPressを開く。タイトルを入れる。本文を貼る。抜粋を入れる。slugを決める。カテゴリーとタグを付ける。SEO titleとdescriptionを入れる。画像をアップロードしてアイキャッチを設定する。
さらに、X、Bluesky、Instagram用の文章を作って、それぞれ投稿する。
文章を書くところだけAIになっても、その後ろには人間の作業がかなり残っていました。
そこで作ったのがPublishing MCPです。
- 最初はn8nに全部つなぐつもりだった
- 対話する仕事と、無人で回る仕事を分けた
- 最初のPublishing MCPは、投稿すらできなかった
- 会話中に内容が変わるので、revisionを持たせた
- 次に、WordPressの「下書きだけ」を作れるようにした
- 「送った」ではなく「届いた」を確認する
- SNSも「3媒体へ同じ文章を送る」ではなかった
- Bufferでも、実運用しないと分からない失敗が出た
- 公開ボタンは、最後まで別にした
- 失敗した媒体だけ、やり直せるようにした
- 画像も、ChatGPTから直接送れるようになった
- 振り返ると、Publishing MCPは「投稿ツール」ではなかった
- それでも、AIは自分から次の仕事を始めなかった
- 連載ナビ
- 関連記事
最初はn8nに全部つなぐつもりだった
当時、サーバーにはすでにn8nを入れていました。
WordPress、SNS、Webhook、定期処理をつなぐなら、最初はかなり自然に、
ChatGPT
↓
n8n
↓
WordPress / SNS
という構成を考えました。
n8nは、決められた処理を繰り返すのには向いています。
毎朝同じ時間に処理する。Webhookを受けたら決まった順番で動く。データをAからBへ運ぶ。監視結果を通知する。
そういう仕事なら、今でもn8nはかなり便利です。
ただ、記事制作を実際にやってみると少し違いました。
タイトルを途中で変える。
「この段落はいらない」と削る。
サムネイルを作り直す。
Xだけ短くする。
Blueskyはスレッドにする。
InstagramはURLを本文へ入れず、プロフィールへ誘導する。
最後になって「今日は公開せず下書きまで」と判断することもあります。
記事は、完成する直前まで形が変わり続けます。
これを最初から固定workflowへ押し込むと、ChatGPTとの会話より、n8nへ渡すJSONや分岐条件を整える方が面倒になってきました。
ここで、「自動化基盤だから全部n8nへ寄せる」という考えをやめました。
対話する仕事と、無人で回る仕事を分けた
そこで役割を分けました。
対話しながら変わる仕事
ChatGPT → Publishing MCP → WordPress / Buffer
決まった形で無人実行する仕事
n8n → 定期処理 / Webhook / 監視
n8nを捨てたわけではありません。
むしろ、n8nを得意な仕事へ戻した形です。
Publishing MCPは、ChatGPTとの会話の途中で変わり続ける記事、SNS文、画像、公開条件を受け止めるための専用工具にしました。
第1回から何度も出てきた考え方ですが、ここでも「便利だから一つへまとめる」のではなく、仕事の性質が違うなら分けています。
最初のPublishing MCPは、投稿すらできなかった
Publishing MCPを作ると決めても、最初からWordPressへ投稿できるようにはしませんでした。
2026年8月1日に実装した最初のP0では、外部サービスへ書き込む機能を持たせていません。
まず作ったのは、Publicationという投稿パッケージを保存する仕組みでした。
Publicationには、たとえば次の情報をまとめます。
- どのサイトの記事か
- WordPress本文
- title / slug / excerpt
- SEO title / meta description
- X用文章
- Bluesky用文章
- Instagram用文章
- 使用する画像
- 公開予定時刻
つまり、いきなり投稿ボタンを作るのではなく、
「何を、どこへ、どの内容で出そうとしているのか」
を一つのデータとして固定するところから始めました。
最初のP0はPublicationの保存、validation、revision管理だけです。
この時点ではWordPressにもBufferにも何も出ません。
かなり地味ですが、後から考えるとこれが重要でした。
会話中に内容が変わるので、revisionを持たせた
記事をChatGPTと作っていると、内容は何度も変わります。
本文を直したあとで、古い状態の投稿処理が残っていたら危険です。
たとえば、
- 記事Aを作る
- 下書き用Publicationを作る
- その後、本文を大きく修正する
- 古いPublicationのまま公開処理を実行する
となれば、確認した内容と違う記事を公開する可能性があります。
そこでPublicationにはrevisionを持たせ、更新するたびに版を進めました。
外部へ書き込む操作では、
「今から実行するのは、このrevisionで間違いないか」
を確認します。
古いrevisionを基準にした操作は拒否する。
Knowledge MCPで文書更新前にSHA-256を確認し、Gitでexpected HEADを確認したのと同じ考え方です。
対象は違っても、またここで、
「見た状態と、実際に変更する状態が同じ時だけ進める」
という原則が出てきました。
次に、WordPressの「下書きだけ」を作れるようにした
P0の次に追加したのがWordPress下書きです。
ここでも、最初から公開はさせませんでした。
Publicationを作る
↓
previewする
↓
WordPressへdraftを作る
↓
内容を確認する
という低リスクなところから始めています。
実際に下書きを作れるようになると、すぐに次の問題が見つかりました。
APIが「成功」と返しても、正しく投稿できているとは限らない。
タイトルは合っているか。
本文は途中で欠けていないか。
slugは合っているか。
カテゴリー・タグは意図どおりか。
CocoonのSEO欄へ正しく入ったか。
アイキャッチは本当に設定されたか。
そこで、投稿したあとにWordPressからもう一度読み戻すようにしました。
「送った」ではなく「届いた」を確認する
WordPress下書き作成後は、実際のWordPressから次を読み戻して照合します。
- title
- 本文のhash
- excerpt
- slug
- category / tag
- draft status
- Cocoon SEO
- featured image
ここはPublishing MCPを作った中でも、かなり重要な設計変更だったと思います。
APIへ命令を送って200 OKが返ることと、目的の状態になっていることは別だからです。
これはブログ投稿に限りません。
外部サービスをAIに操作させるなら、
命令する
↓
成功responseを受ける
だけではなく、
命令する
↓
外部サービスから読み戻す
↓
本当に意図した状態か照合する
まで必要でした。
後にこの考え方は、reconciliationとしてさらに強くなっていきます。
SNSも「3媒体へ同じ文章を送る」ではなかった
WordPressの次にBuffer連携を追加しました。
ここでも、単純に同じ文章を3SNSへ送る形にはしませんでした。
XにはX向けの文章があります。
Blueskyはスレッドにしたいことがあります。
Instagramはクリックできる記事URLを本文へ置くより、プロフィールへの導線にした方が自然です。
画像枚数や縦横比も媒体ごとに違います。
そのためPublicationの中で、媒体ごとの文章と画像を別々に持たせました。
一つの記事
├─ WordPress本文
├─ X用
├─ Bluesky用
└─ Instagram用
同じ内容をコピペするのではなく、一つの発信物から媒体別の完成形を持つようにしたわけです。
現在この連載でも、XとBlueskyはスレッド、Instagramは画像付き要約という形で使っています。
Bufferでも、実運用しないと分からない失敗が出た
もちろん、SNS側も最初からきれいには動きませんでした。
分かりやすかったのが、Bufferのdraftをそのまま即時送信へ変える処理です。
投稿作成時に使う入力と、既存投稿を編集するときに使う入力が微妙に違いました。
その違いを十分に扱えておらず、
送信へ切り替えたつもりなのにdraftのまま残る
可能性がありました。
修正では、作成時だけ必要な値をedit時には送らないようにし、draftを解除する条件を明示し、状態遷移そのものを回帰テストへ入れました。
ここでも学んだのは、
APIは「投稿」という物体だけ見ても足りない。draft → sending → sentのような状態遷移までテストする必要がある
ということでした。
公開ボタンは、最後まで別にした
Publishing MCPで下書きもSNS準備もできるようになると、当然「そのまま公開までやってほしい」となります。
でも、第4回のGitHub PRと同じで、作れることと確定してよいことは別です。
そこで公開系は、
prepare
↓
preview
↓
人が確認
↓
confirmed execution
↓
read-back / reconciliation
にしました。
WordPress公開、予約公開、SNS即時送信は、下書き作成より強い操作として分けています。
「記事を作って」と言っただけで勝手に公開しない。
「この内容で公開して」と確定した時だけ、外部サービスへ出す。
この境界は、GitHubでPRをmergeする時とかなり似ています。
生成と確定を分ける。
コードでも記事でも、同じ原則が使えました。
失敗した媒体だけ、やり直せるようにした
SNSを複数媒体へ出すと、全部が同時に成功するとは限りません。
Xは成功した。
Blueskyも成功した。
Instagramだけ失敗した。
この時、もう一度全部送るとXとBlueskyへ重複投稿してしまいます。
そこで各媒体を別targetとして記録し、成功済みの媒体は再送しないようにしました。
一部だけ失敗したら、その媒体だけ再試行する。
さらに、外部サービス側で送信が完了したあとも、内部DBに古いSending状態が残ることがあります。
そこで後からWordPressやBufferの実状態を読み直し、内部記録と照合するreconcileも追加しました。
単発の自動投稿ではなく、失敗しても続きから直せる運用へ変わっていきました。
画像も、ChatGPTから直接送れるようになった
Publishing MCPを使っていると、画像の受け渡しも面倒になりました。
ChatGPTへ貼った画像を、別の場所へ一度アップロードしてURLを作る。
あるいはBase64へ変換する。
どちらも記事を書くたびにやりたくありません。
そこで、ChatGPTへ添付した画像をPublishing MCPへ直接渡し、対象サイトのWordPressメディアライブラリへ保存する経路を作りました。
ChatGPT添付画像
↓
Publishing MCP
↓
WordPress media library
↓
記事・SNSで再利用
これで、
「この画像をサムネイルにして」
という会話から、そのままWordPressのfeatured imageまでつながるようになりました。
この連載のサムネイルも、今まさにその経路を使っています。
振り返ると、Publishing MCPは「投稿ツール」ではなかった
最初は、WordPressとSNSへ投稿するためのMCPを作っている感覚でした。
でも実際に必要だったのは、単なる投稿APIではありませんでした。
- 何を出すかを一つのPublicationへまとめる
- revisionで内容を固定する
- previewする
- 下書きと公開を分ける
- API成功後に読み戻す
- 媒体ごとの完成形を持つ
- 一部失敗だけ再試行する
- 外部の現実と内部状態を照合する
つまり作っていたのは、
AIが発信物を安全に外へ届けるための境界
だったのだと思います。
Knowledge MCPは記憶の境界。
Development MCPは開発操作の境界。
Development Runnerは強い実行権限の境界。
GitHub PRは変更を確定する境界。
Publishing MCPは公開の境界。
こうして、ChatGPTから「覚える」「作る」「動かす」「確定する」「発信する」能力が一通りそろってきました。
その後、複数Chat・workspace・Workerを並列に動かせるところまで能力を伸ばした結果、別Chatが所有するPublishing MCPのworkspaceまで主開発Chatが進めそうになるという別種のIncidentも起きました。公開境界やfile scopeだけでは足りず、「誰がその仕事を担当してよいか」というownership境界まで必要になった話です。
→ AIが別のChatの仕事まで進めそうになった話――能力向上で生まれた新しい失敗モード
それでも、AIは自分から次の仕事を始めなかった
ここまで来ると、かなり自動化されたように見えます。
実際、ChatGPTから記事を作り、画像を設定し、WordPressへ公開し、SNSまで送れるようになりました。
でも、一つ大きなことは変わっていませんでした。
次に何をするかを決めているのは、まだ毎回自分です。
「この記事を書いて」
「この機能を直して」
「SNSへ投稿して」
と指示すれば動く。
でも、指示しなければ何も始まりません。
Knowledge MCP、Development MCP、Runner、Publishing MCPと、できることを増やしても、それだけではAIは自律化しませんでした。
そこで次に考えることになります。
「能力は揃った。では、次の仕事を決める仕組みを上に置けないか?」
ここからLoop Engineが始まります。この続きは第6回にまとめました。
→ 第6回:MCPをいくつ作っても、AIは自律化しなかった。そこでLoop Engineを作った
連載ナビ
- 第1回:ChatGPTに長期記憶が欲しくて、Knowledge MCPを作った
- 第2回:ChatGPTにコードを書かせるだけでは足りなかった。Development MCPを作った
- 第3回:AIに自分自身を再起動させたら止まった。Development Runnerを分離した
- 第4回:ChatGPTからPRを作り、安全にマージできるようにした
- 第5回:記事を書くだけでは自動化にならなかった。Publishing MCPを作った ← 今回
- 第6回:MCPをいくつ作っても、AIは自律化しなかった。そこでLoop Engineを作った
- 連載一覧


コメント