Claude Codeを使ってMCPサーバーを開発した
📋 全体の概要
成果物: 2つのMCPツール(記事検索・トレンド取得)
概要
- 目的: Zennの記事フィードを取得するMCPサーバーの開発
- 技術スタック: Python 3.10+, FastMCP, TDD
-
開発期間: 3日
- 1日目:ドキュメント準備
- 2日目:開発
- 3日目:開発仕上げ
開発方針
- 日本語優先での開発(筆者が日本語ネイティブなため)
- 厳格なドキュメント管理による知見の蓄積
- TDD(テスト駆動開発)の実践
- ブランチ単位での細かい機能開発と記録
📁 このリポジトリの各種ドキュメントの役割・概要
このプロジェクトでは、Claude Codeとの協働を効率化するため、体系的なドキュメント管理を実施しました。以下が各ドキュメントの役割と概要です。
📋 プロジェクト管理文書
CLAUDE.md
- 役割: Claude Code開発の基本ルールと設定情報
- 内容: 日本語優先開発、TDD規則、ブランチ管理、MCPサーバー設定など
- 特徴: プロジェクト開発中の「憲法」的な位置づけ
docs/requirements.md
- 役割: プロジェクトの要件定義書
- 内容: 機能要件、非機能要件、技術仕様、受け入れ基準
- 特徴: 12章構成の詳細な仕様書、進捗状況も管理
📐 開発プロセス文書
docs/tdd_rule.md
- 役割: テスト駆動開発(TDD)のガイドライン
- 内容: Red-Green-Refactorサイクル、コミット規律、品質基準
- ベース: Kent Beck(『テスト駆動開発』の著者)のGitHubリポジトリ
- 特徴: 構造変更と振る舞い変更の明確な分離
docs/branch_rule.md
- 役割: ブランチ戦略とプルリクエストのルール
- 内容: ブランチ命名規則、PRフォーマット、マージルール
- 特徴: 連番管理による明確な機能単位での開発
📝 作業管理文書
docs/sow/
(6ファイル)
- 役割: 各ブランチ作成時の作業範囲定義(Statement of Work)
- 作成タイミング: ブランチを切る前にClaude Codeが必ず作成
-
ファイル例:
-
01_project_foundation.md
: プロジェクト基盤構築 -
02_article_crawler.md
: 記事クローラー実装 -
06_trending_feed_feature.md
: トレンド記事機能
-
- 効果: 作業範囲の明確化、スコープクリープ防止
docs/dev_log/
(5ファイル)
- 役割: 各機能開発完了時の実装ログ
- 作成タイミング: プルリクエスト作成前
- 内容: 実装内容、技術的な決定事項、学んだこと
- 効果: 知見の蓄積、後続開発への引き継ぎ
📋 計画・設定文書
docs/planning/plan_o3.md
- 役割: o3による初期開発計画
- 内容: 技術検証結果、システム構成案、工数見積もり
- 特徴: 当初は「記事取得→要約→Markdown保存」の機能を想定
docs/github-actions-setup.md
- 役割: Claude Code Actionの設定ガイド
- 内容: GitHub Actions設定、権限管理、環境変数設定
ドキュメント管理の効果
- Claude Codeとの認識齟齬を防止
- 開発知見の確実な蓄積
- プロジェクト全体の透明性向上
- 他の開発者への引き継ぎ容易性
⚙️ 技術スタックの概要
🤖 Claude Code関連技術
Claude Code Action
- 役割: GitHubリポジトリでのClaude自動実行
-
設定:
.github/workflows/
でのYAML設定 - 活用場面: プルリクエスト時の自動レビュー、コード品質チェック
- 効果: 開発者の手動作業削減、一貫した品質管理
gemini-google-search MCPサーバー
- 役割: 開発中の技術調査・仕様確認
-
設定:
~/.claude/.mcp.json
に追加 -
技術構成:
- Vertex AI経由でのGemini API利用
- Google検索結果のリアルタイム取得
-
活用場面:
- ライブラリ・フレームワークの最新情報収集
- エラー解決方法の検索
- 技術仕様の確認
### 🛠️ 開発・運用技術
#### uv(Pythonパッケージマネージャー)
- **役割**: 高速なPython環境管理
- **採用理由**:
- 高速
- 依存関係解決の正確性
- モダン
- **使用コマンド**:
```bash
uv add [package_name] # 依存関係インストール
uv sync
uv run python app/main.py # MCPサーバー起動
uv run pytest # テスト実行
vibelogger
- 役割: 構造化ログ出力
-
特徴:
- 軽量でシンプルな設定
- JSON形式での出力
- Claude Codeによる問題解析支援
- 実装例:
from vibelogger import create_file_logger
# Global logger instance
_logger = None
def setup_logging():
"""Setup vibelogger configuration."""
global _logger
# Create vibelogger instance - it automatically creates ./logs/zenn_mcp/ directory
_logger = create_file_logger("zenn_mcp")
def get_logger(name: str = "zenn_mcp"):
"""Get the vibelogger instance."""
if _logger is None:
setup_logging()
return _logger
MCP Inspector
- 役割: 作成したMCPサーバーのブラウザベーステスト
- URL: https://github.com/modelcontextprotocol/inspector
-
活用目的:
- Claude Code外でのMCPサーバー動作確認
- 開発中のデバッグ・検証
- 成果物の品質保証
-
使用場面:
- 新機能実装後の動作確認
- エラーハンドリングのテスト
- レスポンス形式の検証
🏗️ 開発フレームワーク
FastMCP
- 役割: MCPサーバーの簡単実装
- 特徴: デコレータベースの直感的な記述
- 実装例:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("zenn-mcp")
@mcp.tool()
def search_zenn_articles(topic: str, max_articles: int = 10) -> str:
"""Zennから指定トピックの記事フィードを取得"""
# 実装
pytest + TDD
- 役割: テスト駆動開発の実現
- 特徴: Kent Beck方式のRed-Green-Refactorサイクル
- 品質指標: テストカバレッジ80%以上達成
技術選択の効果
- Claude Codeエコシステム内での一貫した開発体験
- 高速な開発サイクルの実現
- 品質の高いMCPサーバーの構築
- 運用・保守の容易性確保
🚀 開発準備
効果的なClaude Code開発を行うため、本プロジェクトでは計画的な準備フェーズを実施しました。
1️⃣ o3による開発計画作成
docs/planning/plan_o3.md
より)
📋 計画内容(o3(OpenAI)による初期技術検証と開発計画を実施しました:
当初想定機能
- 記事取得: Zennトピック記事の取得
- AI要約: Claude/OpenAI APIによる記事要約
- Markdown出力: 指定パスへの保存機能
技術検証結果
- Zenn APIアクセス: ✅ 無認証で十分取得可能
- 要約機能: ✅ 技術的には実装可能
- Markdown出力: ✅ FastAPIエンドポイントで対応
工数見積もり
- クローラ実装: 0.5日
- 要約ラッパー: 0.5日
- Markdown テンプレート: 0.25日
- FastAPI + MCP化: 0.5日
- 合計: 約2日
📊 実際の開発との比較
- 予定: 2日
- 実際: 3日(13回のプルリクエスト)
- 要因: 要約機能の複雑さ、品質要求の高さ、TDD実践
2️⃣ 各種ドキュメント整備
開発開始前に以下のドキュメント体系を構築:
📝 基本設定文書
CLAUDE.md # 開発の憲法
├── 日本語優先開発
├── TDD規則
├── ブランチ管理
└── MCPサーバー設定
📋 プロセス定義文書
docs/
├── requirements.md # 詳細な要件定義
├── tdd_rule.md # Kent Beck式TDDルール
├── branch_rule.md # ブランチ戦略
└── github-actions-setup.md # CI/CD設定
📁 作業管理テンプレート
docs/
├── sow/ # SOW(作業範囲定義)テンプレート
├── dev_log/ # 開発完了ログテンプレート
└── planning/ # 計画文書保存場所
3️⃣ 開発環境セットアップ
🔧 技術環境
# Python環境
uv add [package_name]
uv sync
# MCP設定
~/.claude/.mcp.json への設定追加
# GitHub Actions
.github/workflows/ への設定ファイル配置
🧪 品質管理環境
# テスト環境
pytest設定
カバレッジ計測設定
# ログ管理
vibelogger設定
logs/ディレクトリ作成
⚙️ 開発の流れ
🔄 基本的な開発サイクル
各機能開発は以下の5ステップで実施:
1️⃣ SOW(作業範囲定義)作成
# ブランチ切る前に必ず実施
docs/sow/XX_feature_name.md を作成
【おおよその記載内容】
- 機能概要
- 技術仕様
- 受け入れ基準
- 技術的課題
- 想定工数
2️⃣ ブランチ作成・開発実施
# ブランチ命名規則に従い作成
git checkout -b feature/zenn_mcp_XX
# TDD サイクルで実装
Red (失敗テスト作成) → Green (実装) → Refactor (構造改善)
3️⃣ 開発ログ作成
# 開発完了時に必ず実施
docs/dev_log/[feature].md を作成
4️⃣ ドキュメント更新
# プルリクエスト作成前に必須実施
1. docs/requirements.md の進捗状況更新
2. 他関連ドキュメントの内容確認・更新
3. 実装した機能の技術仕様を各ドキュメントに反映
5️⃣ プルリクエスト作成
# 標準フォーマットに従い作成
## このタスクの完了条件
- 具体的な完了条件を箇条書き
## 完了条件を満たすために追加した要素
- コンポーネント、関数、テストなど
## 特に見てもらいたい部分
- レビュー重点箇所
6️⃣ レビューとマージ
- Claude Code Actionにレビューをしてもらう
- 人間も軽くチェック
- 問題なければマージ
📊 実際の開発履歴
第1フェーズ: 基盤構築(SOW #1-3)
このフェーズはほとんど無駄になった(体験談で後述)
01_project_foundation.md # プロジェクト基盤
02_article_crawler.md # 記事クローラー
03_integrated_summarization_system.md # 要約システム統合
第2フェーズ: MCP統合(SOW #4)
このフェーズはほとんど無駄になった(体験談で後述)
04_mcp_integration.md # MCP サーバー化
第3フェーズ: 機能簡素化(SOW #5-6)
方針転換し、記事取得機能に絞って実装
05_simplified_feed_retrieval.md # フィード取得の簡素化
06_trending_feed_feature.md # トレンド記事機能
🎯 品質管理プロセス
テスト駆動開発の実践
# 各機能で必ず実施
def test_feature_xxx():
"""機能XXXのテスト - 最初に失敗テストを作成"""
# Given: 初期状態設定
# When: 機能実行
# Then: 期待する結果を検証
コミット規律
docs/tdd_rule.md
を参照
# 以下の条件を全て満たした時のみコミット
✅ 全テストが通過
✅ リンター警告が解消
✅ 単一の論理的作業単位
✅ 構造変更 or 振る舞い変更かを明記
MCP Inspector での検証
# MCPサーバーがおおよそ完成したタイミングで、開発者自身が検証
1. ローカルでMCPサーバー起動
2. MCP Inspector でブラウザテスト
3. 期待通りの動作確認
4. エラーハンドリング検証
🎯 開発体験談
📋 当初の計画
o3による初期計画では、以下の豪華な機能セットを想定:
想定機能フロー
- 記事取得: Zennトピック記事の効率的取得
- AI要約機能: Claude/OpenAI APIによるインテリジェント要約
- Markdown出力: 自動保存
🏔️ 要約機能開発での苦戦
- 要約機能がうまく開発できず
- Claudeに任せ切っていたら「できました」と言ってきたが、実際はただのモックだった
- API経由させて要約させようとしたらうまくできず…
💡 シンプルな構成への方向転換
まずは動くMCPサーバーを作ろうと思い、完成目処のある記事取得機能に絞って実装
最終的なアーキテクチャ
@mcp.tool()
def search_zenn_articles(topic: str, max_articles: int = 10) -> str:
"""Zennから指定トピックの記事フィードを取得"""
# シンプルな記事取得のみに集中
@mcp.tool()
def get_trending_articles(max_articles: int = 10) -> str:
"""Zennから現在のトレンド記事フィードを取得"""
# トレンド記事という付加価値を提供
💭 振り返り
Claude Codeはチャットサービス(ChatGPT, Gemini)、IDE(Cursor, GitHub Copilot)と比べて、一度指示を出したら止まらずに自走する特徴があります。また、自走する際に内部で勝手にタスクを細分化してくれるので、現状(2025年7月末時点)のAIエージェントツールの中ではかなり使い勝手が良く、一番流行っていると思います。
ただ、簡単な指示や小さい実装であれば問題なく自走するのですが、今回のように一から開発をしてもらうような場合は、工夫しないとうまくいかないことが多い感じがします。
この工夫について、個人的な所感と今回の実施状況を以下にまとめて結びとします。
カテゴリ | 項目 | コメント | 実施有無 |
---|---|---|---|
ドキュメント管理 | ドキュメントの充実 | CLAUDE.mdをはじめ、各種ドキュメントを整備しておく。これによってClaude Codeがなるべく迷わず開発できるように誘導するイメージ | ✅ 実施 |
作業管理 | 作業ログの徹底 | 開発の方向が間違ってしまった時に手戻りしやすい | ✅ 実施 |
作業管理 | 機能単位でのプルリクエスト | 開発単位を機能粒度にすることで、作業ログやSOWの内容も機能単位になり、分かりやすい。レビューも機能単位で行える | ✅ 実施 |
コード品質 | LinterやFormatterの設定 | 品質をクリアしないとコミットできないようルール化 | ❌ 未実施 |
コード品質 | テスト駆動開発 | 直感的に「テスト駆動開発するとテストに通らない限りコミットしないし、品質担保されるかな」と思い採用。実際テストは通ったが、そもそもやりたいこととずれていたような感触があった。テスト駆動開発への理解が足りないことや、テスト内容をちゃんと読みきれていないまま進めたことが原因かも | △ 実施したが効果限定的 |
作業効率化 | 複数のClaude Codeで並列開発 | Claude Codeの開発精度が今回よりも高くなって、「基本的に細部は確認しなくても問題なく実装できる」レベルで制御できるなら効果がありそうだが、そうじゃ無い場合は人間の認知負荷が高くなりすぎてしんどいと思っている。参考:https://tolv.jp/blog/claude-code-multi-task/ | ❌ 未実施 |
Discussion