初めてのMCPサーバー開発 - jrnl-mcpを作ってみた
Model Context Protocol(MCP)を使って、コマンドラインジャーナルツール「jrnl」とClaudeを連携させるMCPサーバーを開発しました。初めてのMCPサーバー開発の体験記として、選んだ理由から実装のポイント、学んだことまでを詳しく紹介します。 Model Context Protocol(MCP)を使って、コマンドラインジャーナルツール「jrnl」とClaudeを連携させるMCPサーバーを開発しました。初めてのMCPサーバー開発の体験記として、選んだ理由から実装のポイント、学んだことまでを詳しく紹介します。 Model Context Protocol(MCP)の登場以来、Claudeとさまざまなツールやサービス をつなげるMCPサーバーが次々と公開されています。GitHubを眺めていると、ファ イルシステムやデータベース、各種APIとの連携など、実に多様なMCPサーバーが 開発されているのを見て、「自分でも何か作ってみたい」という気持ちが湧いてきま した。 MCPサーバーを作ることで、自分の日常的なワークフローにAIを組み込めるだけで なく、MCPというプロトコルの仕組みを手を動かしながら理解できる良い機会になる と考えました。 MCPサーバーの題材を考えるにあたって、以下の条件を満たすものを探しました。 これらの条件にぴったり当てはまったのが、コマンドラインジャーナルツールの 「jrnl」でした。 jrnlは、ターミナルから素早く日記を書けるPython製のツールで、タグ付けや検 索機能も備えています。私は日々の作業ログや思考の記録に使っており、「Claude がこのジャーナルのデータにアクセスできたら、過去の記録を踏まえたより良いアド バイスがもらえるのでは」と考えました。 また、jrnlは構造化されたデータ(日付、タグ、本文)を持ちながらも、実装がシ ンプルで、初めてのMCPサーバー開発の題材として適していると判断しました。 そして作成したのが、「jrnl-mcp」です。 開発はClaude Codeをペアプログラミングパートナーとして進めました。まず最初 に、MCPサーバーの基本的な構造についてClaudeに相談し、必要なファイル構成を 決めました。 TypeScriptを選んだのは、MCPのSDKが型定義を提供しており、開発時の補完やエラーチェックが効くためです。Claude Codeと一緒に、まずは最小限の「Hello World」的なMCPサーバーを作り、それが動作することを確認してから機能を追加していくアプローチを取りました。 開発中、特に助かったのは以下の点です。 最終的に実装した機能は以下の5つです。 すべての機能は読み取り専用にしました。これは、誤ってジャーナルを変更してしまうリスクを避けるためと、MCP サーバーの初回実装としてシンプルに保つためです。 MCPサーバーの開発を通じて、以下のような仕組みを理解できました。 MCPには「リソース」と「ツール」という2つの概念があります。 jrnl-mcpではツールのみを実装しましたが、 リソースを使えば「最新の10エントリ」のような動的なコンテンツを提供も可能です。 jrnlコマンドの実行は外部プロセスの起動を伴うため、すべての処理を非同期で実装する必要がありました。Node.jsの MCPサーバーは、エラーが発生してもクライアント(Claude Desktop)に適切にエラーを伝える必要があります。try-catchブロックでエラーをキャッチし、意味のあるエラーメッセージを返すようにしました。 TypeScriptとMCP SDKの型定義のおかげで、ツールの引数や戻り値の型が明確になり、実装ミスを防げました。 開発したMCPサーバーをClaude Desktopで使うためのセットアップ手順は以下の通りです。 動作確認では、「jrnlを使って先週の日記を見せて」「@projectタグの統計を教え て」といったプロンプトで、実際にClaudeがジャーナルのデータにアクセスできる ことを確認しました。 実際に開発してみて気づいたポイントをまとめます。 初めてのMCPサーバー開発は、思っていた以上にスムーズに進みました。Claude Codeのサポートもあり、半日程度で基本的な機能を持つMCPサーバーを作ることが できました。 jrnl-mcpを作ってみて、個人のツールやワークフローとAIを連携させることの可 能性を実感しました。読み取り専用という制限はありますが、過去の記録を活用した アドバイスや分析ができるようになったのは大きな価値です。 MCPは、AIと既存のツールやサービスをつなぐ橋渡し役として、今後ますます重要 になっていくでしょう。この経験を活かして、他のツールとの連携も試してみたいと 思います。 もしMCPサーバー開発に興味がある方は、ぜひ身近なツールから始めてみることを お勧めします。思っているより簡単に、自分だけのAI連携ツールが作れるはずです 。Table of Contents
はじめに - MCPサーバーを作ってみたい
MCPサーバーの題材選び - なぜjrnlを選んだのか
Claude Codeと一緒に開発スタート
jrnl-mcp/
├── src/
│ └── index.ts # メインのサーバー実装
├── package.json # プロジェクト設定
├── tsconfig.json # TypeScript設定
└── README.md # ドキュメントjrnl-mcpの実装と機能
機能 説明 search_entries - エントリ検索 日付範囲、タグ、検索キーワードを指定してジャーナルエントリを検索できます。例えば「先週の@work タグが付いた記事」といった柔軟な検索が可能です。 list_tags - タグ一覧 使用しているすべてのタグとその使用回数を取得します。どんなテーマについて多く書いているかが一目でわかります。 get_statistics - 統計情報 総エントリ数、平均文字数、最もよく書いている時間帯など、ジャーナルの統計情報を取得します。 analyze_tag_cooccurrence - タグ共起分析 どのタグとどのタグが一緒に使われることが多いかを分析します。思考のパターンや関心事の関連性が見えてきます。 list_journals & set_journal - ジャーナル切り替え jrnl は複数のジャーナルを管理できるので、それらを切り替える機能も実装しました。 開発中に学んだMCPの仕組み
リソースとツールの違い
非同期処理の重要性
child_process.execをPromiseでラップして使用しています。エラーハンドリング
型安全性
セットアップと動作確認
git clone https://github.com/yostos/jrnl-mcp
cd jrnl-mcp
npm install
npm run buildnpm link{
"mcpServers": {
"jrnl": {
"command": "jrnl-mcp"
}
}
}npm linkを使うことで、jrnl-mcpというコマンドがグローバルで使えるようになり、設定がシンプルになります。作ってみて分かったMCPサーバー開発のポイント
console.errorでログを出力すると、Claude Desktopのログに表示さ れるので、デバッグに役立つ。まとめ