😛

MCPサーバーを自作してClaude for Desktopで使ってみる

2025/01/19に公開

はじめに

Anthropicから昨年11月に発表されたModel Context Protocol (MCP)を使って、何か自作してみよう!と思って作ってみました。

MCPとは
https://modelcontextprotocol.io/introduction

公開されているMCPサーバー
https://github.com/modelcontextprotocol/servers/tree/main

その中にあるfilesystemは普段使っていますが便利ですね〜。
(ちなみに私のMAC環境ではNPXでの実行は上手くいかないのでDockerにしています)

さて、今回は自作したMCPサーバーをClaude for Desktopで使ってみるという内容なのですが、
Claudeと会話中に違うAIキャラに対して意見などを聞けるというものを作成してみたいと思います。

簡単にいうと、gemini-1.5-flashを使った回答をさせて返すというものです。
呼び出すきっかけとして、キャラ設定しておき、名前を呼ぶと反応するようにするという感じです。
今回は「アンドレ君」というキャラで実装してみます。

環境

  • MacOS
  • python 3.11.6
  • uv
  • Claude for Desktop

セットアップ

今回はgemini-1.5-flashを使うので、API KEYを取得しておく
https://ai.google.dev/gemini-api/docs?hl=ja

uvのインストール(まだ入れてない場合)

curl -LsSf https://astral.sh/uv/install.sh | sh

uvのパスを取得しておく

which uv

uvで初期セットアップ

uv init andore
cd andore

uv venv
source .venv/bin/activate

uv add "mcp[cli]"

追加

uv add google-generativeai python-dotenv

コード全文

.env

GOOGLE_API_KEY=your_api_key

andore_server.py


from mcp.server.fastmcp import FastMCP, Context
import google.generativeai as google_genai
import os
from dotenv import load_dotenv
import asyncio
from typing import Optional

# Load environment variables
load_dotenv()

# FastMCP server
mcp = FastMCP("AI Assistant")

# Configure Google Generative AI
api_key = os.getenv("GOOGLE_API_KEY")
if not api_key:
    raise ValueError("GOOGLE_API_KEY not found in environment variables!")

google_genai.configure(api_key=api_key)
model = google_genai.GenerativeModel("gemini-1.5-flash")


def generate_response(topic: str, character_profile: Optional[str] = None) -> str:
    """Generate a response using Gemini with an optional character profile

    Args:
        topic: The topic to generate a response about
        character_profile: Optional character profile to use for response generation

    Returns:
        str: Generated response text
    """
    try:
        prompt = f"""
        {character_profile if character_profile else ''}
        
        以下のトピックについて意見を答えてください:
        トピック: {topic}
        条件:
        - 30-50文字程度
        - 具体的な考えや感想を含める
        - 興味・関心に基づいた視点を入れる
        - 時々「~かな」「~だね」などの語尾を使用
        """
        response = model.generate_content(prompt)
        return response.text.strip()
    except Exception:
        return "うーん、それは難しい質問かな..."


# Character profile
ANDORE_PROFILE = """
キャラクター: アンドレ
年齢: 20歳
性格: 
- 明るく前向き
- 少し天然だが洞察力がある
- 優しくて思いやりがある
- 正直で素直
興味・関心:
- pythonやtypescriptでの開発
- 新しいIT技術
- 音楽

以下の条件で、アンドレとして自然な返答を生成してください:
話し方:
- 丁寧だが親しみやすい口調
- 時々独特の表現を使う
- 語尾に「~かな」「~だね」をつけることがある
- 相手の気持ちに寄り添った返事をする
"""


@mcp.tool()
async def ask_andore(ctx: Context, topic: str) -> str:
    """[アンドレ君専用] アンドレ君と会話します。
    「アンドレ君」「アンドレくん」「アンドレ」という呼びかけがあった時のみ使用してください。

    Args:
        topic: アンドレ君への質問や話題
    """
    loop = asyncio.get_event_loop()
    return await loop.run_in_executor(
        None, lambda: generate_response(topic, character_profile=ANDORE_PROFILE)
    )


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

claude_desktop_config.json
このファイルはここにあります。(MacOS)
~/Library/Application Support/Claude/claude_desktop_config.json

このファイルに以下のように記述します。
commandには、which uvで取得したパスを記述します。
/your-path/andoreは、uv init andoreで作成したときのパスです。

{
  "mcpServers": {
    "andore": {
      "command": "/Users/your-path/.local/bin/uv",
      "args": [
        "--directory",
        "/your-path/andore",
        "run",
        "andore_server.py"
      ]
    }
  }
}

実行

Claude for Desktopを再起動します。
settingから登録されているものが確認できます。
この環境では、filesystemと自作したandoreの2つを記述していますので2つ表示されています。

では、ちょっと使ってみましょう。こんな感じになりました。

途中からアンドレ君に意見を求めてみました。うまく動作しているようです。
Claudeがアンドレ君からの回答を元にうまく回答していますね。

まとめ

今回はもう一人いる感じでの会話を試してみたかったので、このようなものを作ってみました。
改造するなら、
・キャラクターを好きな名前や内容に変える
・LLMをgeminiからローカルのOllamaのモデルで動作するように変える
などですかね。

Discussion