1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code から Qiita に下書きを投げる MCP サーバーを作った記録

1
Last updated at Posted at 2026-06-19

やったこと

将棋エンジン「技巧」を触っている開発リポジトリに、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)で記事を量産してみて、生成精度や手間を見ていきます。

追記:閲覧系ツールを追加した(2026-06-24)

公開後に運用してみて、「自分の公開済み記事が一覧から見えない」ことに気づきました。原因は API の制約ではなく、一覧ツールが非公開記事だけを返すフィルタになっていたためです。ついでに「他人の記事を検索して連載のネタや参考記事を探したい」という要望も出てきたので、閲覧系のツールを3つ追加しました。

追加したのは次の3つです。

  • list_my_qiita_items … 自分の記事一覧を取得する。visibility で公開/非公開/全件を切り替えられる(既定は全件)
  • search_qiita_items … Qiita全体をキーワード検索する。tag: user: stocks:>10 などの修飾子も使える
  • list_qiita_items_by_tag … 指定したタグの記事一覧を取得する

これで合計7ツールになりました。設計方針として「閲覧と投稿で公開範囲のポリシーを分ける」ことにしています。

  • 閲覧系(一覧・取得・検索)は、公開記事や他人の記事も対象にできる
  • 新規作成は意図しない公開を防ぐため常に private(非公開・限定共有)。更新は記事の現在の公開状態を維持する

注意点として、Qiita では一度全体公開した記事を限定共有(非公開)に戻すことはできません(手段は削除のみ)。そのため公開記事への更新は即時反映されます。update_qiita_item は記事の現在の公開状態をそのまま維持する作りにし、公開前に内容を確認したい場合は「限定共有のまま編集・確認し、確定してから一度だけ公開する」運用にしています。

なお、この「公開記事は非公開へ戻せない」という挙動は実際に踏んでから気づいたものです。もし Qiita の仕様や API についてもっと良い運用・正確な情報をご存じの方がいれば、ぜひコメントで教えていただけると嬉しいです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?