ブログ記事をObsidianで書き、WordPressで公開する運用では、最後の「下書きへ送る」段階が危険になりやすい。本文に個人情報が残っていたり、同じslugの記事を重複作成したり、誤って公開まで進めてしまうと、あとから修正する手間が大きい。そこで今回は、Hermes AgentからWordPressへ直接公開するのではなく、Obsidianの記事を検査してWordPressの下書きだけへ同期する安全ゲートを作った。
実際に行ったこと
プロジェクト側には、WordPress REST APIを呼ぶ中核処理、stdio MCPサーバー、日次同期用CLIを分けて配置した。記事本文は公式Obsidian CLIでBlog用Vaultから読み取り、Markdownのfrontmatterを検査してから、WordPress REST APIの投稿payloadへ変換する。MCPツールとしては、接続確認、カテゴリ・タグ一覧、下書き作成前のprepare、確認コード付きsyncだけを公開した。公開や削除のツールは持たせていない。
動作確認は単体テストで行った。uv run python -m unittest tests.test_wordpress_blog tests.test_wordpress_daily_publish tests.test_blog_cron_prompt -v を実行し、9件のテストが成功した。確認した内容は、MarkdownからGutenbergブロックへの変換、個人メールや個人絶対パスの検出、同一slugの二重作成防止、書き込みスイッチと確認コードの強制、MCPに公開・削除ツールが出ていないこと、cron配置時にプロジェクトを解決できることなどである。
仕組みの流れ
処理は次の順番にした。
- 公式Obsidian CLIでVault内の記事を読み取る。
- frontmatterからtitle、slug、status、categories、tags、excerptを取り出す。
- 記事本文に個人絶対パス、実メールアドレス、Webhook URL、トークンらしい文字列がないか検査する。
- WordPress側のカテゴリ・タグをREST APIで取得し、記事指定と照合する。
- 同じslugの既存投稿をdraftとpublishに分けて確認する。
- 作成・更新・noopのいずれかをprepareで返し、payload hashから確認コードを発行する。
- sync時に同じ内容を再検査し、確認コードが一致し、書き込み許可が有効な場合だけ下書きを作る。
この二段階にしたことで、Hermes Agentが「作成する内容」と「実際に送る内容」を同じpayload hashで結び、途中で記事が変わった場合は再prepareが必要になる。
再現手順
最小構成では、次のように環境変数を用意する。秘密値は必ずプレースホルダーから置き換え、最初は書き込みを無効にする。
WORDPRESS_BASE_URL=https://example.com
WORDPRESS_USERNAME=your-user
WORDPRESS_APP_PASSWORD=YOUR_WORDPRESS_APP_PASSWORD
WORDPRESS_ENABLE_DRAFT_WRITES=false
WORDPRESS_OBSIDIAN_CLI=/path/to/obsidian-cli
WORDPRESS_OBSIDIAN_VAULT=Blog00
次に、記事フォルダを許可リストに入れ、MCPサーバーをHermesへ登録する。手元の実装では、下書き同期用サーバーはstdioで起動し、MCPのtools/listとtools/callに応答する。
hermes mcp add wordpress \
--command /path/to/python \
--args /path/to/project/wordpress_mcp_server.py
hermes mcp test wordpress
初回はwordpress_statusとwordpress_list_taxonomiesだけを確認し、次にwordpress_prepare_obsidian_draftで対象記事を検査する。問題がなければ、書き込み許可を有効にして新しいHermesセッションを開始し、prepareで返った確認コードを使ってwordpress_sync_obsidian_draftを実行する。
失敗しやすい点と安全策
WordPressの権限によっては、REST APIのstatus=anyが使えないことがある。そのため手元の実装では、draftとpublishを別々に検索して重複を確認した。また、Obsidian側の記事に公開済みのIDが付いている場合や、同じslugが公開済みの場合は停止する。タグが存在しない場合はmissingとして扱えるが、カテゴリ不足は記事分類が崩れるためエラーにした。
未完了事項もある。この仕組みは下書き同期までで、公開、削除、予約投稿は扱わない。公開判断は別の確認フローに分ける。また、正規表現による秘密情報検査は万能ではないため、公開前には人の目での最終確認が必要である。
再現チェックリスト
- [ ] Obsidian CLIで対象Vaultの記事をreadできる。
- [ ] WordPress REST APIで現在のユーザー、カテゴリ、タグを取得できる。
- [ ]
WORDPRESS_ENABLE_DRAFT_WRITES=falseではsyncが拒否される。 - [ ] prepare結果に作成・更新・noopと確認コードが出る。
- [ ] 同じslugを再実行しても重複投稿にならない。
- [ ] MCPツール一覧にpublish/delete系ツールがない。
- [ ] テストが成功し、実記事に個人情報や秘密値が残っていない。
