🐈

会員登録不要のWeb検索MCPサーバーを作ってみた (CrewAI + DuckDuckGo)

に公開

初めに

Web検索系のMCPサーバーを探していた時に見つけたDuckDuckGO MCPサーバーを内包して作成したMCPサーバーです。
DuckDuckGO MCPサーバーだけでも十分にWeb上の情報を取得してくれますが、CrewAIと掛け合わせることで高精度なレポートを作成することができます。
また、実行したタスクからRAGを作って効率的に情報を取得できるので、Web検索タスクと相性がいいです。
これをMCPサーバーとして作成することで、MCP接続に対応している他のシステムにも簡単にWeb検索機能を実装することができます。
※ OpenAI APIキーが必要になります。

実装

main.py
from crewai.memory import LongTermMemory, ShortTermMemory
from crewai.memory.storage.ltm_sqlite_storage import LTMSQLiteStorage
from crewai.memory.storage.rag_storage import RAGStorage
from crewai_tools import MCPServerAdapter
from langchain_openai import ChatOpenAI
from mcp import StdioServerParameters
from mcp.server.fastmcp import FastMCP

from crew import get_web_search_crew


def main() -> None:
    server_params = StdioServerParameters(
        command="uvx",
        args=["duckduckgo-mcp-server"],
    )
    short_term_memory = ShortTermMemory(
        storage=RAGStorage(type="short_term", path="db/short"),
    )
    long_term_memory = LongTermMemory(
        storage=LTMSQLiteStorage(db_path="db/chroma.sqlite3"),
    )
    with MCPServerAdapter(server_params, connect_timeout=60) as mcp_tools:
        llm = ChatOpenAI(model="gpt-4o-mini", temperature=0, verbose=True)
        crew = get_web_search_crew(short_term_memory, long_term_memory, llm, mcp_tools)
        mcp_server = FastMCP(name="web_search_mcp_server")

        @mcp_server.tool()
        def search_website(query: str) -> str:
            """Web検索の結果をレポートとして出力する"""
            result = crew.kickoff(inputs={"query": query})

        mcp_server.run("stdio")


if __name__ == "__main__":
    main()
crew.py
from crewai import Agent, Crew, Process, Task
from crewai.memory import LongTermMemory, ShortTermMemory
from crewai.tools import BaseTool
from langchain_core.language_models import BaseChatModel


def get_web_search_crew(short_term_memory: LongTermMemory, long_term_memory: ShortTermMemory, base_llm: BaseChatModel, web_search_tool: list[BaseTool]) -> Crew:
    general_agent = Agent(
        role="汎用エージェント",
        goal="指示されたタスクを実行する",
        backstory="""
            あなたは汎用性に優れたエージェントです。
            与えられたタスクの指示に従ってください。
            """,
        verbose=True,
        llm=base_llm,
    )
    web_search_agent = Agent(
        role="Webキーワード検索者",
        goal="与えられたキーワードからツールを使って広範囲にWeb検索を実行する",
        backstory="""
            あなたは優秀なWebリサーチャーです。
            下記のツールをタスクごとに使い分けてください。
            - search
                - キーワード検索。
            - fetch_content
                - URLのコンテンツを取得する。
            """,
        tools=web_search_tool,
        reasoning=True,
        verbose=True,
        llm=base_llm,
    )
    generate_search_keyword_task = Task(
        description="""
            クエリからWeb検索をするための検索キーワードを生成する。
            文脈から考察して無駄なキーワードは添削してください。

            ---
            クエリ:
            {query}
            """,
        expected_output="""
            空白区切りの検索キーワード

            ---
            例:
            pythonのuvについてディープリサーチして -> python uv
            LangChainでMCPを利用する方法を教えて -> LangChain MCP 利用 方法
            """,
        agent=general_agent,
        name="generate_search_keyword_task",
    )
    collect_url_task = Task(
        description="searchツールを実行してキーワードを検索して、URLと軽い説明のリスト収集する。",
        expected_output="URLと説明のリスト",
        agent=web_search_agent,
        name="web_search_task",
    )
    fetch_content_task = Task(
        description="fetch_contentツールを実行して、URLのコンテンツを取得してコンテンツ情報を取得する。",
        expected_output="URLとURLのコンテンツ情報",
        agent=web_search_agent,
        name="fetch_content_task",
    )
    create_report_task = Task(
        description="""
            クエリに対する回答レポートを前工程で取得した情報を参考にして作成してください。

            ---
            クエリ:
            {query}
            """,
        expected_output="""
            # Rule
            - 作成した資料は確実にメモリに保存してください。
            - メモリを検索して関連する資料があるか確認してください。
            - マークダウン形式で日本語で回答してください。
            - 情報量を詰め込んで出来るだけ長いレポートを作成してください。
            - 参考リンクを明示してください。
            """,
        agent=general_agent,
        name="create_report_task",
    )
    add_reference_url_task = Task(
        description="参考リンクを明示する",
        expected_output="""
            レポートの末尾に参考リンクが無ければ、下記の参考リンク例のような段落を追加する。

            ---
            参考リンク例:
            ## 参考リンク
            - [example](https://example.com)
            """,
        agent=general_agent,
        name="create_report_task",
    )
    return Crew(
        agents=[general_agent, web_search_agent],
        tasks=[
            generate_search_keyword_task,
            collect_url_task,
            fetch_content_task,
            create_report_task,
            add_reference_url_task,
        ],
        verbose=True,
        cache=True,
        share_crew=True,
        process=Process.sequential,
        memory=True,
        long_term_memory=long_term_memory,
        short_term_memory=short_term_memory,
    )

プロンプトはまだまだ改善の余地がありそうです。

CrewAIのメリット

  • メモリ機能を使ってタスクの履歴からRAGを作れる。
  • 自律的にWebページのコンテツを取得させれる。
  • 作成したいレポートのフォーマットを指定できる。

実行例

例としてLangChain MCP Adaptersを経由して、MCPサーバーについて検索してもらいます。

質問:
MCPサーバーとは何かWeb検索して

# MCPサーバーに関する詳細レポート

## 1. MCPサーバーの概要
MCP(Model Context Protocol)サーバーは、AIモデルが外部のデータソースやツールと標準化された方法で連携できるようにするためのオープンプロトコルです。このプロトコルにより、AIはリアルタイムで情報を取得し、より正確な回答を生成することが可能になります。MCPサーバーは、AIエージェントが外部リソースにアクセスするための中介役を果たします。

## 2. MCPの特徴
- **標準化**: すべてのAIが同じ手順で外部サービスにアクセスできるため、開発者は一貫したインターフェースを利用できます。
- **安全性**: 認証・許可の仕組みを組み込むことができ、データの安全性を確保します。
- **拡張性**: 自作プラグインで機能を追加できるため、特定のニーズに応じたカスタマイズが可能です。

## 3. MCPの動作
MCPは、AIエージェント(クライアント)がMCPサーバーを介して外部リソースにアクセスし、情報を取得する仕組みです。以下のステップで動作します:
1. **初期化**: クライアントがMCPサーバーに接続し、必要な設定を行います。
2. **サーバー機能の問い合わせ**: クライアントがサーバーの提供する機能を確認します。
3. **サーバーの機能呼び出し**: 必要な機能を呼び出し、処理を依頼します。
4. **機能の実行**: サーバーがリクエストに基づいて処理を実行します。
5. **結果の返答**: 処理結果がクライアントに返され、次のアクションに利用されます。

## 4. 具体的な活用例
- **GitHub MCP**: プルリクエストの作成やイシューの編集、コメントの投稿などをAIが自動で実行します。
- **Notion MCP**: メモやドキュメントの自動作成・整理が可能で、作業効率を向上させます。
- **Slack MCP**: チャンネル管理やメッセージングをサポートし、コミュニケーションの円滑化を図ります。

## 5. MCPサーバーの実装手順
MCPサーバーを実装するためには、以下の手順が必要です:
1. **開発環境のセットアップ**: 必要なソフトウェアやライブラリをインストールします。
2. **サーバーの実装**: プロトコルに基づいてサーバーの機能を実装します。
3. **MCPクライアントとの接続設定**: クライアントとサーバーの接続を設定し、テストを行います。

## 6. MCPの課題と将来性
MCPにはセキュリティリスクやスケーラビリティの問題がありますが、将来的にはより多くのAIプラットフォームがMCPに対応し、AIエージェントの機能が拡張されることが期待されています。特に、データのプライバシーやセキュリティを強化するための技術的な進展が求められています。

## 7. 参考リンク
- [MCP公式ドキュメント](https://modelcontextprotocol.io/introduction)
- [徹底解説 MCPサーバーを6つの主要カテゴリに分類(2025年版) - Qiita](https://qiita.com/syukan3/items/5c3c9321d713bc1d8ecf)
- [AIエージェント MCPサーバーって何? - Zenn](https://zenn.dev/tomo0108/articles/6b472b4c9cacfa)
- [MCPサーバーの基礎から用途別おすすめ一覧まで|株式会社dotConf](https://note.com/dotconf/n/ndc8823740d72)
- [【2025年最新】Model Context Protocol (MCP)サーバー完全技術ガイド|アーキテクチャから実装まで徹底解説](https://tasukehub.com/articles/mcp-server-technical-guide-2025/)

この情報をもとに、MCPサーバーの導入や活用を検討してみてください。AIの可能性を広げるための強力なツールとなるでしょう。

しっかりレポートが作成されています。
試しにduckduckgoのみでも実行してみます。

MCPサーバーについての情報を以下にまとめます。

1. **MCPサーバーの主要カテゴリ** - Qiitaでは、MCPサーバーを6つの主要カテゴリに分類しています。これにより、利用頻度や注目度に基づいた理解が得られます。詳細は[こちら](https://qiita.com/syukan3/items/5c3c9321d713bc1d8ecf)で確認できます。

2. **Model Context Protocolのリポジトリ** - GitHubにあるMCPサーバーのリポジトリでは、モデル・コンテキスト・プロトコル(MCP)のリファレンス実装やコミュニティによって構築されたサーバーが紹介されています。詳細は[こちら](https://github.com/modelcontextprotocol/servers)で確認できます。

3. **MCPサーバーの歴史と基本情報** - Zennの記事では、MCPが「Model Context Protocol」の略であり、Anthropic社によって提唱されたオープンソースのプロトコルであることが説明されています。このプロトコルにより、AIモデルが外部のデータソースやツールにアクセスできるようになります。詳細は[こちら](https://zenn.dev/tomo0108/articles/6b472b4c9cacfa)で確認できます。

4. **MCPサーバーの概要と使い方** - dotConfの記事では、MCPサーバーの概要や使用方法、用途別のおすすめサーバーが紹介されています。AI技術を活用する方にとって重要な情報が含まれています。詳細は[こちら](https://note.com/dotconf/n/ndc8823740d72)で確認できます。

5. **MCPサーバーの技術ガイド** - Tasukehubの記事では、MCPサーバーの技術的仕様、アーキテクチャ、API仕様、実装方法について詳しく解説されています。開発者向けの包括ガイドとして役立ちます。詳細は[こちら](https://tasukehub.com/articles/mcp-server-technical-guide-2025/)で確認できます。

これらのリソースを参考に、MCPサーバーについての理解を深めることができます。

少しコストが掛かりますがCrewAIによるリサーチを中継することで、高品質なレポートが出力されていますね。

来栖川電算

Discussion