やったこと
将棋エンジン「技巧」を触っている開発リポジトリに、Claude から Qiita 記事を
非公開(限定共有)下書きとして投稿できる MCP サーバーを組み込みました。
コミット履歴や会話の内容から、開発日記風の記事を半自動で生成して Qiita に
保存する、という運用を目指したものです。この記事自体もその仕組みで書いています。
背景・きっかけ
開発の作業ログを Qiita にまとめたいものの、毎回エディタを開いて書き起こすのが
面倒で続きませんでした。そこで Claude Code から直接 Qiita に投稿できれば、
「作業 → そのまま記事化」の流れが作れるのでは、と考えて MCP サーバーを
自作することにしました。
変更内容
3 つのコミットで段階的に組み込みました。
-
Qiita 記事投稿用 MCP サーバーの追加 …
MCP/server.pyを実装。
Qiita API v2 を叩く 4 つのツール(作成・更新・一覧・取得)を公開する。 -
記事下書き作成スキルの追加 …
/qiita-draftスラッシュコマンドを追加。
git コミットや会話スレッドから記事本文を生成する手順をスキル化。 -
Claude Code 用の MCP 設定追加 … リポジトリ直下に
.mcp.jsonを置き、
プロジェクトスコープで Qiita MCP を有効化。README に手順を追記。
サーバーは mcp / httpx / python-dotenv だけの薄い実装です。記事作成は
こんな具合で、必ず private: True を付けて投稿します。
payload = {
"title": arguments["title"],
"body": arguments["body"],
"tags": build_tags(arguments["tags"]),
"private": True, # 必ず非公開(限定共有)として作成
"tweet": False,
}
resp = await client.post(f"{QIITA_API_BASE}/items", headers=qiita_headers(), json=payload)
ハマったところ
-
Qiita API に「下書き」が無い … API v2 には下書き専用のエンドポイントが
ありません。仕方なく記事をprivate(限定共有)として作成し、公開は Qiita の
Web 画面から手動で行う運用に割り切りました。 -
uv syncがプロジェクト自身をビルドしようとして失敗 … 単一スクリプトとして
動かしたいだけなのに hatchling のビルドが走ってこけました。pyproject.tomlに
[tool.uv] package = falseを入れて回避。 -
トークンの読み込み場所 …
uv run --directory MCPで起動するとカレント
ディレクトリがズレて.envを見失うので、server.py側で
Path(__file__).resolve().parent.parent / ".env"と絶対パス指定にしました。 -
アクセストークンの管理 … Qiita のアクセストークンは漏れると記事を勝手に
操作されかねないので、コードや設定ファイルに直書きせず.envに置き、
.gitignoreに.envを追加して Git 管理から除外しました。MCP サーバー側は
python-dotenvで.envを読み込み、Claude Code の.mcp.jsonでは
${QIITA_ACCESS_TOKEN}として環境変数を展開する形にしています。なお.envを
書き換えても、起動中の MCP サーバーは古い値を保持したままなので、反映には
サーバーの再接続(/mcpで reconnect)が必要でした。 -
Claude Desktop と Claude Code で設定が別 … Desktop は
claude_desktop_config.json、CLI 版はリポジトリ直下の.mcp.json。
CLI 側はトークンをファイルに直書きせず${QIITA_ACCESS_TOKEN}を展開する形にして、
起動シェルの環境変数から渡すようにしました。
まとめ
claude mcp list で qiita: ✔ Connected を確認できたところまで来ました。
これで「手を動かした内容をそのまま記事化」する下地ができたので、次は実際に
コミット起点(モードA)で記事を量産してみて、生成精度や手間を見ていきます。