FastMCP:数分で MCP サーバーを構築する(2026年)
AIアシスタント向けのカスタムMCPサーバーを構築する最短の方法
Hyperealで構築を始めよう
Kling、Flux、Sora、Veoなどに単一のAPIでアクセス。無料クレジットで開始、数百万規模まで拡張可能。
クレジットカード不要 • 10万人以上の開発者 • エンタープライズ対応
FastMCP: 数分で MCP サーバーを構築する (2026)
Model Context Protocol (MCP) は、AI アシスタントを外部ツールやデータに接続するための新しい標準規格です。しかし、MCP サーバーをゼロから構築するのは手間がかかる作業です。トランスポート、シリアライズ、プロトコルの詳細の管理に時間を費やすべきではありません。
FastMCP はこれを解決します。これは高レベルな Python フレームワークであり、Flask や FastAPI アプリを構築するように、デコレータを使って完全に機能する MCP サーバーを構築できます。このガイドでは、数分でゼロから動作する MCP サーバーを作成する方法を説明します。
FastMCP とは?
FastMCP は、MCP SDK を開発者フレンドリーな API でラップしたオープンソースの Python ライブラリです。プロトコルメッセージやトランスポート層を手動で処理する代わりに、デコレータを使用してシンプルな Python 関数を記述します。
| 機能 | Raw MCP SDK | FastMCP |
|---|---|---|
| サーバーのセットアップ | 約30行のボイラープレート | 2行 |
| ツールの定義 | 手動のスキーマ + ハンドラ | @mcp.tool() デコレータ |
| リソースの定義 | 手動の URI + ハンドラ | @mcp.resource() デコレータ |
| 型の処理 | 手動の JSON Schema | 型ヒントから自動生成 |
| テスト | 手動のトランスポートモック | 内蔵テストクライアント |
| コード行数 (シンプルなサーバー) | 80-100行 | 15-20行 |
インストール
pip install fastmcp
FastMCP には Python 3.10 以上が必要です。
初めての MCP サーバーの構築
以下は、15行のコードで記述された完全な MCP サーバーです。
# server.py
from fastmcp import FastMCP
mcp = FastMCP("my-tools")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers together."""
return a + b
@mcp.tool()
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
# 本番環境では、実際の天気 API を呼び出します
return f"The weather in {city} is 72F and sunny."
if __name__ == "__main__":
mcp.run()
これだけです。FastMCP は以下の処理を自動的に行います:
- 型ヒントから JSON スキーマを生成。
- MCP プロトコル(ツール一覧、ツール呼び出し、エラーハンドリング)の処理。
- Claude Code、Claude Desktop、およびその他の MCP クライアントとの互換性のための stdio トランスポートのセットアップ。
サーバーの実行
python server.py
Claude Code への接続
.mcp.json または Claude Code の設定に追加します:
{
"mcpServers": {
"my-tools": {
"command": "python",
"args": ["/path/to/server.py"]
}
}
}
または Claude Code CLI を使用します:
claude mcp add my-tools python /path/to/server.py
コアコンセプト
ツール (Tools)
ツールは、AI が呼び出すことができる関数です。アクションを実行し、結果を返します。
from fastmcp import FastMCP
import httpx
mcp = FastMCP("dev-tools")
@mcp.tool()
def search_npm(query: str, limit: int = 5) -> str:
"""Search npm registry for packages."""
response = httpx.get(
f"https://registry.npmjs.org/-/v1/search",
params={"text": query, "size": limit}
)
results = response.json()["objects"]
lines = []
for pkg in results:
p = pkg["package"]
lines.append(f"- {p['name']} (v{p['version']}): {p.get('description', 'No description')}")
return "\n".join(lines)
@mcp.tool()
def run_sql(query: str, database: str = "main.db") -> str:
"""Execute a read-only SQL query against a SQLite database."""
import sqlite3
conn = sqlite3.connect(database)
conn.execute("PRAGMA query_only = ON")
cursor = conn.execute(query)
columns = [desc[0] for desc in cursor.description] if cursor.description else []
rows = cursor.fetchall()
conn.close()
if not rows:
return "No results."
header = " | ".join(columns)
separator = " | ".join(["---"] * len(columns))
data = "\n".join([" | ".join(str(cell) for cell in row) for row in rows])
return f"{header}\n{separator}\n{data}"
リソース (Resources)
リソースは、AI が読み取ることができるデータを公開します。これらは URI によって識別されます。
@mcp.resource("config://app")
def get_app_config() -> str:
"""Return the application configuration."""
import json
with open("config.json") as f:
return json.dumps(json.load(f), indent=2)
@mcp.resource("file://{path}")
def read_file(path: str) -> str:
"""Read a file from the project directory."""
with open(path) as f:
return f.read()
@mcp.resource("db://schema")
def get_database_schema() -> str:
"""Return the database schema."""
import sqlite3
conn = sqlite3.connect("main.db")
cursor = conn.execute(
"SELECT sql FROM sqlite_master WHERE type='table'"
)
schemas = [row[0] for row in cursor.fetchall()]
conn.close()
return "\n\n".join(schemas)
プロンプト (Prompts)
プロンプトは、AI が使用できる再利用可能なプロンプトテンプレートです。
@mcp.prompt()
def code_review(code: str, language: str = "python") -> str:
"""Generate a code review prompt."""
return f"""Review the following {language} code for:
1. Security vulnerabilities
2. Performance issues
3. Code style and best practices
4. Potential bugs
Code:
```{language}
{code}
Provide specific, actionable feedback with code examples for fixes."""
@mcp.prompt() def explain_error(error_message: str, stack_trace: str = "") -> str: """Generate an error explanation prompt.""" prompt = f"Explain this error and suggest fixes:\n\nError: {error_message}" if stack_trace: prompt += f"\n\nStack trace:\n{stack_trace}" return prompt
## 実践的な例: GitHub MCP サーバー
より完成度の高い例として、GitHub リポジトリのツールを提供する MCP サーバーを以下に示します。
```python
# github_mcp.py
from fastmcp import FastMCP
import httpx
import os
mcp = FastMCP("github-tools")
GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "")
HEADERS = {"Authorization": f"Bearer {GITHUB_TOKEN}"} if GITHUB_TOKEN else {}
@mcp.tool()
def search_repos(query: str, limit: int = 5) -> str:
"""Search GitHub repositories."""
response = httpx.get(
"https://api.github.com/search/repositories",
params={"q": query, "per_page": limit},
headers=HEADERS
)
repos = response.json().get("items", [])
lines = []
for repo in repos:
lines.append(
f"- [{repo['full_name']}]({repo['html_url']}) "
f"({repo['stargazers_count']} stars): {repo['description'] or 'No description'}"
)
return "\n".join(lines) or "No repositories found."
@mcp.tool()
def get_repo_readme(owner: str, repo: str) -> str:
"""Get the README content of a GitHub repository."""
response = httpx.get(
f"https://api.github.com/repos/{owner}/{repo}/readme",
headers={**HEADERS, "Accept": "application/vnd.github.raw+json"}
)
if response.status_code == 200:
return response.text
return f"Error: Could not fetch README ({response.status_code})"
@mcp.tool()
def list_issues(owner: str, repo: str, state: str = "open", limit: int = 10) -> str:
"""List issues for a GitHub repository."""
response = httpx.get(
f"https://api.github.com/repos/{owner}/{repo}/issues",
params={"state": state, "per_page": limit},
headers=HEADERS
)
issues = response.json()
lines = []
for issue in issues:
labels = ", ".join([l["name"] for l in issue.get("labels", [])])
lines.append(f"- #{issue['number']}: {issue['title']} [{labels}]")
return "\n".join(lines) or "No issues found."
@mcp.tool()
def get_file_contents(owner: str, repo: str, path: str, ref: str = "main") -> str:
"""Get the contents of a file from a GitHub repository."""
response = httpx.get(
f"https://api.github.com/repos/{owner}/{repo}/contents/{path}",
params={"ref": ref},
headers={**HEADERS, "Accept": "application/vnd.github.raw+json"}
)
if response.status_code == 200:
return response.text
return f"Error: Could not fetch file ({response.status_code})"
@mcp.resource("github://repos/{owner}/{repo}/info")
def get_repo_info(owner: str, repo: str) -> str:
"""Get basic information about a GitHub repository."""
response = httpx.get(
f"https://api.github.com/repos/{owner}/{repo}",
headers=HEADERS
)
repo_data = response.json()
return (
f"Name: {repo_data['full_name']}\n"
f"Stars: {repo_data['stargazers_count']}\n"
f"Language: {repo_data['language']}\n"
f"Description: {repo_data['description']}\n"
f"URL: {repo_data['html_url']}"
)
if __name__ == "__main__":
mcp.run()
これを登録します:
{
"mcpServers": {
"github": {
"command": "python",
"args": ["/path/to/github_mcp.py"],
"env": {
"GITHUB_TOKEN": "ghp_your_token"
}
}
}
}
MCP サーバーのテスト
FastMCP にはテストクライアントが内蔵されています:
# test_server.py
import asyncio
from fastmcp import Client
async def test():
async with Client("python server.py") as client:
# 利用可能なツールを一覧表示
tools = await client.list_tools()
print(f"Available tools: {[t.name for t in tools]}")
# ツールを呼び出す
result = await client.call_tool("add", {"a": 5, "b": 3})
print(f"5 + 3 = {result}")
# リソースを一覧表示
resources = await client.list_resources()
print(f"Available resources: {[r.uri for r in resources]}")
asyncio.run(test())
FastMCP vs. Raw MCP SDK
同じツールを両方の方法で定義した比較です:
Raw MCP SDK
from mcp.server import Server
from mcp.types import Tool, TextContent
import json
server = Server("my-server")
@server.list_tools()
async def list_tools():
return [
Tool(
name="add",
description="Add two numbers",
inputSchema={
"type": "object",
"properties": {
"a": {"type": "integer", "description": "First number"},
"b": {"type": "integer", "description": "Second number"}
},
"required": ["a", "b"]
}
)
]
@server.call_tool()
async def call_tool(name, arguments):
if name == "add":
result = arguments["a"] + arguments["b"]
return [TextContent(type="text", text=str(result))]
FastMCP
from fastmcp import FastMCP
mcp = FastMCP("my-server")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
FastMCP バージョンは4行であるのに対し、Raw SDK は25行以上かかります。多くのツールを持つサーバーでは、この差は劇的に大きくなります。
MCP サーバーを構築するためのヒント
- 小さく始める。 1つか2つのツールを構築してテストし、それから拡張します。
- 型ヒントを使用する。 FastMCP は型ヒントから JSON スキーマを自動生成します。
- 適切な docstring を記述する。 AI はツールの説明を読み、いつそれを使用するかを判断します。
- エラーを適切に処理する。 例外を発生させるのではなく、エラーメッセージを文字列として返します。
- ツールの焦点を絞る。 1つのツールは1つのことをうまく行うべきです。AI にそれらを組み合わせさせましょう。
- 環境変数を使用する。 API キーや設定は MCP 設定内の
envを通じて渡します。
まとめ
FastMCP は MCP サーバー構築からボイラープレートを排除し、実際の機能に集中できるようにします。API のラップ、データベースへの接続、カスタム開発ツールの構築など、あらゆるアイデアを数分で動作する MCP サーバーに変えることができます。
MCP ツールで画像、ビデオ、オーディオ、アバターなどのメディアを生成する必要がある場合は、Hypereal AI を無料でお試しください。35クレジット提供、クレジットカード不要です。その REST API は、AI を活用したメディア生成のために、あらゆる MCP サーバーに簡単に統合できます。
