6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Cursor上で最近読んだ本から次のおすすめを提案してくれるブクログAPI連携MCPサーバーを作ってみた

6
Last updated at Posted at 2025-12-26

はじめに

皆さん、こんにちは!アディクシィ株式会社の野中康生と申します。

突然ですが、Amazonのおすすめ本って、いまいちしっくりこないことありませんか?

そこで私は普段からブクログで読書記録をつけているのですが、「自分の読書履歴をAIに見せて、次に読むべき本を提案してもらえたら便利なのでは?」と思いました。

そこで今回、ブクログの読書記録を活用して、Cursor上で「最近読んだ推しに関する本から次のおすすめを提案して」と聞くだけで、AIが読書履歴を分析して次に読むべき本を提案してくれる仕組みを作ってみました!

ブクログAPIとMCPサーバーを活用することで、自分の読書履歴を元にした、本当に的確なおすすめ本をAIに提案してもらえるようになります。

ブクログAPI × MCPで実現できること

今回作成したMCPサーバーを使うと、以下のようなことができます:

  1. 最近読んだ本の取得:登録日順に最新の読書記録を取得
  2. キーワード検索:本棚の中から特定のテーマの本を検索
  3. 次に読むべき本の提案:読んだ本を踏まえた上で次に読むべき本を提案してくれる
  4. 記事作成支援:読書リストをマークダウン形式で出力

技術スタック

  • Cursor: 我らがIDE
  • ブクログAPI: 本棚情報の取得
  • BeautifulSoup4: 個別書籍の詳細情報のスクレイピング
  • MCP (Model Context Protocol): Cursorとの連携
  • FastMCP: MCPサーバーの簡単な構築

環境構築

1. Pythonバージョンの確認

python --version
# Python 3.12.0 を例

2. 必要なパッケージのインストール

プロジェクトディレクトリを作成し、必要なパッケージをインストールします。

mkdir booklog-mcp-server
cd booklog-mcp-server
python -m venv venv
source venv/bin/activate
pip install mcp httpx beautifulsoup4 python-dotenv

3. ブクログユーザーIDの確認

ブクログのプロフィールURLからユーザーIDを確認します:

https://booklog.jp/users/your_user_id
                        ↑ これがユーザーID

.envファイルを作成し、ユーザーIDを保存します:

BOOKLOG_USER_ID=your_user_id

MCPサーバーの実装

booklog_mcp_server.pyを作成します:

#!/usr/bin/env python3
"""
Booklog MCP Server

MCPサーバーとしてブクログAPIへのアクセスを提供します。
読書記録から次に読むべき本のおすすめを提案できます。
"""

import os
import asyncio
import httpx
from bs4 import BeautifulSoup
from mcp.server.fastmcp import FastMCP
from dotenv import load_dotenv

# 環境変数の読み込み
load_dotenv()
BOOKLOG_USER_ID = os.getenv("BOOKLOG_USER_ID", "")

# MCPサーバーの初期化
mcp = FastMCP("Booklog MCP Server")


@mcp.tool()
async def get_recent_books(user_id: str = None, count: int = 10) -> dict:
    """
    最近読んだ本を取得します(登録日の新しい順)
    
    Args:
        user_id: ブクログのユーザーID
        count: 取得する書籍数(デフォルト: 10)
    
    Returns:
        最近読んだ本のリスト(登録日、タイトル、Amazonリンク付き)
    """
    if user_id is None:
        user_id = BOOKLOG_USER_ID
    
    # まず書籍リストを取得
    url = f"http://api.booklog.jp/v2/json/{user_id}"
    params = {"count": min(count * 2, 100)}
    
    async with httpx.AsyncClient(timeout=30.0) as client:
        response = await client.get(url, params=params)
        response.raise_for_status()
        data = response.json()
        
        books_with_details = []
        
        # 各書籍の詳細情報を取得
        for book in data.get("books", [])[:count]:
            try:
                detail_response = await client.get(book.get("url", ""))
                soup = BeautifulSoup(detail_response.content, "html.parser")
                
                # 登録日を取得
                register_date = None
                date_elem = soup.find(class_="read-day-status-area")
                if date_elem:
                    date_span = date_elem.find("span")
                    if date_span:
                        register_date = date_span.text.strip()
                
                # Amazonリンクを取得
                amazon_link = None
                item_info = soup.find(class_="itemInfoElm")
                if item_info:
                    link_elem = item_info.find("a")
                    if link_elem:
                        amazon_link = link_elem.get("href")
                
                books_with_details.append({
                    "title": book.get("title", ""),
                    "register_date": register_date,
                    "amazon_link": amazon_link,
                    "booklog_url": book.get("url", ""),
                    "image": book.get("image", "")
                })
                
                # レート制限を考慮
                await asyncio.sleep(0.5)
                
            except Exception as e:
                print(f"Error: {e}")
                continue
        
        # 登録日でソート
        books_with_details.sort(key=lambda x: x.get("register_date", ""), reverse=True)
        
        return {
            "user_id": user_id,
            "count": len(books_with_details),
            "books": books_with_details
        }


@mcp.tool()
async def search_books_by_keyword(user_id: str = None, keyword: str = "") -> dict:
    """
    ブクログの本棚からキーワードで書籍を検索します
    
    Args:
        user_id: ブクログのユーザーID
        keyword: 検索キーワード(タイトルに含まれる文字列)
    
    Returns:
        検索結果の書籍リスト
    """
    if user_id is None:
        user_id = BOOKLOG_USER_ID
    
    url = f"http://api.booklog.jp/v2/json/{user_id}"
    params = {"count": 10000}
    
    async with httpx.AsyncClient() as client:
        response = await client.get(url, params=params)
        response.raise_for_status()
        data = response.json()
        
        filtered_books = []
        keyword_lower = keyword.lower()
        
        for book in data.get("books", []):
            title = book.get("title", "")
            if keyword_lower in title.lower():
                filtered_books.append({
                    "title": title,
                    "url": book.get("url", ""),
                    "image": book.get("image", "")
                })
        
        return {
            "user_id": user_id,
            "keyword": keyword,
            "total_found": len(filtered_books),
            "books": filtered_books
        }


if __name__ == "__main__":
    mcp.run()

ポイント

  1. ブクログAPI: http://api.booklog.jp/v2/json/{user_id} で本棚情報を取得
  2. スクレイピング: 個別の書籍詳細ページから登録日とAmazonリンクを取得
  3. レート制限: 0.5秒の待機時間でサーバーに優しく

Cursorへの登録

Cursorの設定ファイル ~/.cursor/mcp.json を開き、以下を追加します:

{
  "mcpServers": {
    "booklog": {
      "command": "/absolute/path/to/your/venv/bin/python",
      "args": [
        "/absolute/path/to/your/booklog_mcp_server.py"
      ],
      "type": "stdio"
    }
  }
}

重要なポイント:

  • commandには仮想環境内のPythonの絶対パスを指定
  • argsにはMCPサーバーファイルの絶対パスを指定
  • type: "stdio"を必ず追加

設定後、Cursorを再起動してください。

実際に使ってみた!

Cursor上で以下のように質問してみました:

booklogで、読み終わった推しに関する5冊の本を新しいものから教えてください。
それを元に次に読むべきおすすめの本を3冊提案してください。

取得できた推し活関連の本(最新5冊)

  1. 「推し」の科学 プロジェクション・サイエンスとは何か (2025年11月15日)

    • 集英社新書
    • 心理学・脳科学的な「推し」のメカニズムを解説
  2. 推し問答!あなたにとって「推し活」ってなんですか? (2025年10月24日)

    • TOKYO NEWS MOOK
    • 様々な推し活のあり方を紹介
  3. 「推し」の文化論 BTSから世界とつながる (2025年10月17日)

    • K-POPを通じたグローバルな文化現象の考察
  4. NHK あさイチ 教えて推しライフ 推し活大全 (2025年10月5日)

    • 実践的な推し活ガイド
  5. オタクと推しの経済学 (2025年10月5日)

    • オタク市場の経済規模や仕組みの解説

AIが提案してくれた次に読むべき本3冊

1. 『ファンダム・レボリューション SNS時代の新たな熱狂』(早川書房)

AIの推薦理由:

『「推し」の文化論』でBTSを通じた世界とのつながりを学び、『オタクと推しの経済学』で市場の仕組みを理解されたあなたに、ファンダムが持つ社会変革の力を国際的な視点で示してくれる一冊です。K-POP、ハリウッド、コミコンなど、世界中のファンコミュニティがどのようにSNSを通じて社会や政治に影響を与えているかを豊富な事例で解説。

2. 『熱狂顧客戦略』(日本経済新聞出版)

AIの推薦理由:

『オタクと推しの経済学』で経済的側面を学び、『推し問答!』で推し活の多様性を知ったあなたに、企業やブランドがどのように「推される存在」になるのかを、マーケティングの視点から解説する本書をおすすめします。

3. 『参与観察 グレーテル化する社会のエスノグラフィ』(左右社)

AIの推薦理由:

「推し」という現象を外から分析するのではなく、自らがその中に入り込んで理解する手法は、あなた自身の推し活をより深く内省する助けになります。文化人類学的なアプローチで、日常の中の特別な瞬間を再発見できる一冊です。

他にもこんな使い方ができるはず

ケース1: ブログ記事の作成

最近読んだ10冊から「2024年に読んで良かった本10選」という
ブログ記事の下書きを作ってください

ケース2: 読書傾向の分析

今年読んだ本を分析して、私の読書傾向を教えてください

ケース3: 特定テーマの本を探す

ブクログに登録している本の中から「Python」関連の本を全て教えてください

ケース4: 読書計画の立案

最近読んだ経済学の本を元に、次の3ヶ月で読むべき本を5冊提案してください

まとめ

今回、ブクログAPIとMCPサーバーを組み合わせることで、Cursor上で「最近読んだ本から次のおすすめを提案して」と聞くだけで、AIが読書履歴を分析して的確なおすすめ本を提案してくれる仕組みを作りました。

ブクログを使っている方は、ぜひ試してみてください。次に読むべき「運命の一冊」に出会えるはずです!
それでは、良い読書ライフを!

参考リンク

6
0
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
6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?