コンテンツにスキップ

MCPサーバー自作 調査・計画

📁 docs/dev-environment/artifact/wip/20260313_MCPサーバー自作_調査・計画.md

作成日: 2026-03-13 目的: 個人開発でMCPサーバーを自作するための調査結果と実装計画


1. MCPサーバとは何か

1.1 MCPの概要

MCP(Model Context Protocol) は、AIアプリケーションと外部システムを接続するためのオープンソース標準プロトコル。USBのように「AI版の統一コネクタ」として機能し、一度サーバーを作れば、Claude Code、Claude Desktop、VS Code (Copilot)、Cursor、ChatGPTなど複数のクライアントから利用できる。

1.2 アーキテクチャ(Host / Client / Server)

┌─────────────────────────────────────────┐
│          MCP Host(AIアプリケーション)         │
│  例: Claude Code, Claude Desktop, VS Code │
│                                         │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐ │
│  │MCP Client│  │MCP Client│  │MCP Client│ │
│  │    #1    │  │    #2    │  │    #3    │ │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘ │
└───────┼──────────────┼──────────────┼──────┘
        │              │              │
  ┌─────▼─────┐  ┌─────▼─────┐  ┌─────▼─────┐
  │MCP Server │  │MCP Server │  │MCP Server │
  │(ローカル)  │  │(ローカル)  │  │(リモート)  │
  │ Filesystem│  │  MyLab    │  │  Sentry   │
  └───────────┘  └───────────┘  └───────────┘
参加者 役割
Host AIアプリケーション本体。複数のClientを管理する(例: Claude Code)
Client Host内部のコンポーネント。1つのServerとの接続を維持する
Server コンテキスト(ツール・データ・プロンプト)を提供するプログラム

1.3 3つの主要プリミティブ

プリミティブ 用途
Tools LLMが実行できるアクション(副作用あり) ファイル操作、API呼び出し、DB クエリ
Resources 読み取り専用のデータ提供(副作用なし) ファイル内容、DB スキーマ、API レスポンス
Prompts 再利用可能なテンプレート システムプロンプト、few-shot 例

1.4 通信方式

方式 概要 用途
stdio 標準入出力でJSON-RPCをやりとり ローカルサーバー(最も一般的)
Streamable HTTP HTTP POST + SSE リモートサーバー(推奨)
SSE (非推奨) Server-Sent Events レガシー互換

個人開発でClaude Codeと組み合わせる場合は stdio が最もシンプル。

1.5 既存MCPサーバーの代表例

公式リファレンスサーバー

サーバー名 概要
Filesystem ファイルシステムへの安全なアクセス
Git Gitリポジトリの読取・検索・操作
Memory ナレッジグラフベースの永続メモリ
Fetch Webコンテンツの取得と変換
Sequential Thinking 段階的推論プロセスのサポート

コミュニティ/パートナー(一部)

  • Sentry - エラー監視・デバッグ
  • GitHub - PR/Issue/コードレビュー
  • Notion - ページ検索・作成
  • Playwright - ブラウザ自動操作
  • PostgreSQL (dbhub) - データベースクエリ

MCP Registryに130以上のサーバーが登録されている。


2. 自作MCPサーバーの候補アイデア

現状の把握

既に projects/mcp-server-mylab/server.py に以下のツールを持つMCPサーバーが存在する: - GitHub Issue管理(list/get/create/close/search) - ファイル検索(名前パターン/内容grep) - プロジェクト管理(一覧/ドキュメント/サマリー)

また scripts/mcp/youtube_transcribe_server.py にYouTube文字起こしサーバーもある。

以下は まだ存在しない、作ったら便利な MCPサーバーのアイデア。


アイデア一覧

# 名前 概要 難易度 推奨言語
1 Obsidian Vault サーバー ノート検索・作成・リンク探索 Easy Python
2 n8n ワークフロー操作サーバー ワークフロー一覧/実行/有効化 Medium Python
3 AI漫画パイプラインサーバー SD WebUI連携で画像生成 Hard Python
4 Google Tasks同期サーバー タスクの取得・作成・更新 Medium Python
5 情報キュレーションサーバー HN/GitHub Trending/Zennの収集・要約 Medium Python
6 SD WebUI Forgeサーバー 画像生成APIのMCPラッパー Medium Python
7 Credentials管理サーバー 認証情報の安全な取得 Easy Python
8 会話ログ管理サーバー ログの保存・検索・要約 Easy Python
9 Discord Bot管理サーバー メッセージ送信・チャンネル操作 Medium Python
10 MyLab統合ダッシュボードサーバー 全プロジェクトの横断的ステータス Medium Python

各アイデアの詳細

1. Obsidian Vault サーバー

概要: Obsidian Vaultのノートを検索・作成・編集できるMCPサーバー。Claude Codeから「あのメモどこだっけ」「新しいメモ作って」が可能に。

提供するTools: | ツール | 説明 | |--------|------| | search_notes | ノートのタイトル/内容をキーワード検索 | | read_note | 指定パスのノートを読み取り | | create_note | 新しいノートを作成(フォルダ指定可) | | update_note | 既存ノートの内容を更新 | | list_recent_notes | 最近更新されたノート一覧 | | get_backlinks | 指定ノートへのバックリンク一覧 |

提供するResources: | リソース | 説明 | |----------|------| | vault://structure | Vaultのフォルダ構造 | | vault://daily/{date} | デイリーノートの内容 |

難易度: Easy(ファイルシステム操作のみ) 推奨言語: Python


2. n8n ワークフロー操作サーバー

概要: n8nのREST APIを叩いて、ワークフローの一覧表示・実行・有効化/無効化ができる。「バズコレクタのワークフロー実行して」のような操作が可能。

提供するTools: | ツール | 説明 | |--------|------| | list_workflows | ワークフロー一覧(名前・状態) | | get_workflow | ワークフロー詳細(ノード構成含む) | | execute_workflow | ワークフローを手動実行 | | toggle_workflow | 有効化/無効化の切替 | | list_executions | 実行履歴(成功/失敗/時刻) | | get_execution_log | 特定の実行の詳細ログ |

難易度: Medium(n8n REST API理解が必要) 推奨言語: Python 前提: n8nインスタンスのAPIキー


3. AI漫画パイプライン サーバー

概要: AI漫画パイプライン(projects/ai-manga-pipeline/)をMCP経由で操作。プロンプトからの画像生成、レイアウト適用、パイプライン全体の実行が可能。

提供するTools: | ツール | 説明 | |--------|------| | generate_image | プロンプトから画像生成(SD WebUI API経由) | | apply_layout | ページレイアウトの適用 | | run_pipeline | パイプライン全体の実行 | | list_prompts | prompt-libraryの一覧 | | preview_page | 生成結果のプレビュー |

難易度: Hard(SD WebUI API + 画像処理 + 既存パイプラインとの統合) 推奨言語: Python


4. Google Tasks 同期サーバー

概要: 既存の scripts/task_sync/ の機能をMCP化。Google Tasksのタスクを直接操作できる。

提供するTools: | ツール | 説明 | |--------|------| | list_tasks | タスクリストの一覧 | | get_tasks | 特定リストのタスク取得 | | create_task | タスク作成 | | complete_task | タスクを完了にする | | sync_with_github | GitHub Issueとの同期実行 |

難易度: Medium(Google API認証が必要) 推奨言語: Python


5. 情報キュレーション サーバー

概要: scripts/insight/ のHacker News/GitHub Trending収集機能をMCP化。「今日のテックニュースまとめて」が1コマンドで可能。

提供するTools: | ツール | 説明 | |--------|------| | fetch_hackernews | HN トップストーリー取得 | | fetch_github_trending | GitHub Trending取得 | | fetch_zenn_likes | Zennの人気記事取得 | | summarize_articles | 取得記事のAI要約 | | save_digest | ダイジェストをファイルに保存 |

提供するResources: | リソース | 説明 | |----------|------| | insight://latest | 最新のダイジェスト | | insight://history/{date} | 過去のダイジェスト |

難易度: Medium(既存スクリプトのラッパー) 推奨言語: Python


6. SD WebUI Forge サーバー

概要: Stable Diffusion WebUI ForgeのAPIをMCPでラップ。テキストから画像生成、モデル切替、LoRA選択などをClaude Codeから操作。

提供するTools: | ツール | 説明 | |--------|------| | txt2img | テキストから画像生成 | | img2img | 画像を元に変換生成 | | list_models | 利用可能なモデル一覧 | | list_loras | 利用可能なLoRA一覧 | | get_progress | 現在の生成進捗 |

難易度: Medium(REST APIのラッパーだが画像データの扱いが複雑) 推奨言語: Python


7. Credentials 管理サーバー

概要: Credentials/ ディレクトリの認証情報を安全に取得するMCPサーバー。他のサーバーやスクリプトが認証情報を必要とする際に使える。

提供するTools: | ツール | 説明 | |--------|------| | list_credentials | 利用可能な認証情報の名前一覧(値は含まない) | | get_credential_key | 特定サービスの特定キーを取得 |

難易度: Easy(JSONファイル読み取りのみ) 推奨言語: Python 注意: セキュリティ上、出力をログに残さない設計が必要


8. 会話ログ管理サーバー

概要: scripts/conversation/logs/ の会話ログをMCPから操作。ログの保存・検索・要約ができる。

提供するTools: | ツール | 説明 | |--------|------| | save_log | 会話ログを保存 | | search_logs | 過去ログをキーワード検索 | | list_recent_logs | 最近のログ一覧 | | summarize_log | 指定ログの要約を生成 |

難易度: Easy(ファイル操作 + 既存スクリプトの活用) 推奨言語: Python


9. Discord Bot 管理サーバー

概要: Discord Botの操作をMCPから行う。メッセージ送信、チャンネル一覧、特定チャンネルの最近のメッセージ取得など。

提供するTools: | ツール | 説明 | |--------|------| | send_message | 指定チャンネルにメッセージ送信 | | list_channels | チャンネル一覧 | | get_recent_messages | 最近のメッセージ取得 | | send_notification | 通知メッセージ送信 |

難易度: Medium(Discord API/Webhook連携) 推奨言語: Python


10. MyLab統合ダッシュボード サーバー

概要: MyLab全体の横断的なステータスを提供。各プロジェクトの最新コミット、n8nワークフローの状態、GitHub Issueの進捗を統合表示。

提供するTools: | ツール | 説明 | |--------|------| | get_dashboard | 全体ダッシュボード表示 | | get_project_status | 特定プロジェクトの詳細ステータス | | get_weekly_summary | 今週の作業サマリー |

提供するResources: | リソース | 説明 | |----------|------| | dashboard://overview | リアルタイム概要 |

難易度: Medium(複数データソースの集約) 推奨言語: Python


3. MCPサーバーの実装方法

3.1 公式SDK

SDK 言語 パッケージ 特徴
Python SDK Python mcp FastMCPフレームワーク、デコレータベース
TypeScript SDK TypeScript @modelcontextprotocol/sdk Node.js向け

個人開発でPythonメインなら Python SDK (FastMCP) 一択。

3.2 最小構成サンプルコード

"""
最小構成のMCPサーバー例
pip install "mcp[cli]" でインストール
"""
from mcp.server.fastmcp import FastMCP

# サーバーインスタンス作成
mcp = FastMCP("my-server")


# === Tool(LLMが実行するアクション)===
@mcp.tool()
def greet(name: str) -> str:
    """指定された名前に挨拶する"""
    return f"こんにちは、{name}さん!"


@mcp.tool()
def add(a: int, b: int) -> int:
    """2つの数値を加算する"""
    return a + b


# === Resource(読み取り専用データ)===
@mcp.resource("info://server")
def server_info() -> str:
    """サーバー情報を返す"""
    return "これはMyLabのテスト用MCPサーバーです。"


@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """パーソナライズされた挨拶"""
    return f"ようこそ、{name}さん!"


# === Prompt(再利用テンプレート)===
@mcp.prompt()
def code_review(language: str = "python") -> str:
    """コードレビュー用のプロンプトテンプレート"""
    return f"以下の{language}コードをレビューしてください。バグ、改善点、ベストプラクティスの観点でフィードバックしてください。"


# エントリーポイント
if __name__ == "__main__":
    mcp.run()  # デフォルトはstdio

3.3 stdio と HTTP/SSE の違い

項目 stdio Streamable HTTP
通信 標準入出力(stdin/stdout) HTTP POST + SSE
起動 親プロセス(Host)がサーバーを起動 独立したHTTPサーバーとして起動
ネットワーク 不要(ローカルのみ) 必要(リモート対応可)
クライアント数 1対1 1対多
用途 ローカル開発、個人利用 チーム共有、リモートアクセス
起動方法 mcp.run() mcp.run(transport="streamable-http")

個人開発の推奨: stdio(最もシンプルで、Claude Codeとの相性が良い)

3.4 Claude Code への登録方法

方法1: CLIコマンド(推奨)

# stdioサーバーの登録
claude mcp add --transport stdio mylab -- python D:/Kazuma_Teramachi/MyLab/projects/mcp-server-mylab/server.py

# スコープ指定(ローカル=デフォルト / プロジェクト / ユーザー)
claude mcp add --transport stdio --scope user mylab -- python server.py

# HTTPサーバーの登録
claude mcp add --transport http my-server http://localhost:8000/mcp

# 環境変数付き
claude mcp add --transport stdio --env API_KEY=xxx myserver -- python server.py

方法2: .mcp.json ファイル(プロジェクト共有向け)

プロジェクトルートに .mcp.json を置く:

{
  "mcpServers": {
    "mylab": {
      "command": "python",
      "args": ["projects/mcp-server-mylab/server.py"]
    }
  }
}

方法3: JSON直接指定

claude mcp add-json mylab '{"type":"stdio","command":"python","args":["projects/mcp-server-mylab/server.py"]}'

管理コマンド

claude mcp list          # 一覧
claude mcp get mylab     # 詳細
claude mcp remove mylab  # 削除

Claude Code内では /mcp コマンドで状態確認・認証が可能。

Windows 注意点

npx を使うサーバーは cmd /c ラッパーが必要:

claude mcp add --transport stdio my-server -- cmd /c npx -y @some/package

3.5 デバッグ方法

MCP Inspector(公式ツール)

# インストール不要、npxで起動
npx -y @modelcontextprotocol/inspector

# ブラウザが開く → サーバーURLを入力して接続
# stdioサーバー: コマンドを指定して起動
# HTTPサーバー: http://localhost:8000/mcp を入力

MCP Inspectorでできること: - ツール一覧の確認 - ツールの手動実行とレスポンス確認 - リソース/プロンプトの確認 - JSON-RPCメッセージのモニタリング

ログ出力

from mcp.server.fastmcp import FastMCP, Context
from mcp.server.session import ServerSession
import logging

logging.basicConfig(level=logging.DEBUG)

mcp = FastMCP("debug-server")

@mcp.tool()
async def debug_tool(message: str, ctx: Context[ServerSession, None]) -> str:
    """デバッグ用ツール"""
    await ctx.info(f"実行中: {message}")  # クライアントにログ送信
    return f"OK: {message}"

Claude Code内でのデバッグ

# Claude Code上で /mcp コマンドを実行してサーバーの状態を確認
/mcp

4. 推奨する「最初の1本」

推奨: Obsidian Vault サーバー

評価軸 スコア 理由
難易度 Easy ファイルシステム操作のみ。外部API不要
有用性 日常的にObsidianを使っている。ノート検索・作成の需要大
学習効果 Tool/Resource/Prompt の3プリミティブすべてを実装できる
既存資産との重複 なし まだObsidian連携のMCPサーバーは未作成
拡張性 タグ検索、テンプレート適用、デイリーノート自動生成など拡張しやすい

既存の mcp-server-mylab はGitHub Issue/ファイル検索に特化しており、Obsidian Vaultサーバーは別の価値を提供する。

実装計画(ステップ)

Step 1: プロジェクトセットアップ(30分)

# ディレクトリ作成
mkdir -p projects/mcp-server-obsidian

# 依存パッケージ
pip install "mcp[cli]"

ファイル構成:

projects/mcp-server-obsidian/
├── server.py      # MCPサーバー本体
├── README.md      # 使い方
└── tests/
    └── test_server.py

Step 2: 基本ツール実装(1時間)

from mcp.server.fastmcp import FastMCP
from pathlib import Path
import re

VAULT_ROOT = Path("D:/Kazuma_Teramachi/MyLab/vault")

mcp = FastMCP("obsidian-vault")

@mcp.tool()
def search_notes(query: str, limit: int = 20) -> str:
    """Vault内のノートをキーワード検索する"""
    results = []
    for md in VAULT_ROOT.rglob("*.md"):
        try:
            content = md.read_text(encoding="utf-8", errors="ignore")
            if query.lower() in content.lower() or query.lower() in md.stem.lower():
                # タイトル(最初のH1または ファイル名)
                title = md.stem
                for line in content.splitlines():
                    if line.startswith("# "):
                        title = line[2:].strip()
                        break
                rel = md.relative_to(VAULT_ROOT)
                results.append(f"- **{title}** (`{rel}`)")
                if len(results) >= limit:
                    break
        except Exception:
            continue
    if not results:
        return f"'{query}' に一致するノートが見つかりませんでした。"
    return f"## 検索結果: '{query}' ({len(results)}件)\n\n" + "\n".join(results)

@mcp.tool()
def read_note(path: str) -> str:
    """指定パスのノートを読み取る(Vaultルートからの相対パス)"""
    note = VAULT_ROOT / path
    if not note.exists():
        return f"ノートが見つかりません: {path}"
    return note.read_text(encoding="utf-8", errors="ignore")

@mcp.tool()
def create_note(path: str, content: str) -> str:
    """新しいノートを作成する"""
    note = VAULT_ROOT / path
    if note.exists():
        return f"既にノートが存在します: {path}"
    note.parent.mkdir(parents=True, exist_ok=True)
    note.write_text(content, encoding="utf-8")
    return f"ノートを作成しました: {path}"

@mcp.tool()
def list_recent_notes(limit: int = 10) -> str:
    """最近更新されたノートを一覧する"""
    notes = sorted(
        VAULT_ROOT.rglob("*.md"),
        key=lambda p: p.stat().st_mtime,
        reverse=True,
    )[:limit]
    lines = [f"## 最近更新されたノート({len(notes)}件)\n"]
    for n in notes:
        rel = n.relative_to(VAULT_ROOT)
        lines.append(f"- `{rel}`")
    return "\n".join(lines)

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

Step 3: Resource/Prompt追加(30分)

@mcp.resource("vault://structure")
def vault_structure() -> str:
    """Vaultのフォルダ構造を返す"""
    # トップレベルのフォルダ一覧
    ...

@mcp.resource("vault://daily/{date}")
def daily_note(date: str) -> str:
    """デイリーノートを返す(例: 2026-03-13)"""
    ...

@mcp.prompt()
def new_note_template(topic: str) -> str:
    """新しいノートのテンプレートプロンプト"""
    return f"「{topic}」について以下の構成でノートを作成してください:\n- 概要\n- キーポイント\n- 参考リンク\n- 次のアクション"

Step 4: テスト・デバッグ(30分)

# MCP Inspectorで動作確認
npx -y @modelcontextprotocol/inspector

# Claude Codeに登録
claude mcp add --transport stdio obsidian-vault -- python D:/Kazuma_Teramachi/MyLab/projects/mcp-server-obsidian/server.py

# 動作確認
claude mcp list
# Claude Code内で /mcp → 状態確認

Step 5: ドキュメント整備・コミット(15分)

  • README.md作成(ツール一覧、起動方法、設定方法)
  • issueにコメント更新
  • コミット&プッシュ

総所要時間の見積もり: 約3時間


参考リンク