MCP サーバー セットアップ完全ガイド:インストール・環境変数・ポート/証明書設定の最短手順

AI アシスタントとデータソースをシームレスに連携させるための新しい標準プロトコル、Model Context Protocol(MCP)。その中核を担う MCP サーバーのセットアップは、現代の AI 開発において避けては通れない重要なステップです。
しかし、初めて MCP サーバーを構築しようとすると、インストール方法、環境変数の管理、トランスポートの選択、証明書の設定など、多くの設定項目に直面します。公式ドキュメントは充実していますが、情報が分散しており、全体像を掴みにくいという課題があるでしょう。
本記事では、MCP サーバーのセットアップに必要な全ての手順を、インストールから環境変数設定、ポート/トランスポート設定、証明書設定まで、一つひとつ段階的に解説します。この記事を読み終える頃には、あなたも自信を持って MCP サーバーを構築できるようになっているはずです。
背景
Model Context Protocol(MCP)の概要
Model Context Protocol(MCP)は、Anthropic が提唱する、AI アシスタントと外部システムを接続するためのオープンプロトコルです。従来、AI アシスタントが外部データにアクセスするには、個別のカスタム統合を構築する必要がありました。
MCP はこの課題を解決し、標準化された方法で AI アシスタントとデータソースを接続可能にします。これにより、Google Drive、Slack、GitHub、データベースなど、さまざまなシステムとの統合が容易になります。
MCP アーキテクチャの 3 つのコンポーネント
MCP のアーキテクチャは、以下の 3 つの主要コンポーネントで構成されています。
以下の図で、MCP の全体構造を確認しましょう。
mermaidflowchart TB
subgraph host["MCP ホスト"]
client["MCP クライアント"]
end
subgraph servers["MCP サーバー群"]
server1["MCP サーバー A<br/>(例: GitHub)"]
server2["MCP サーバー B<br/>(例: Slack)"]
server3["MCP サーバー C<br/>(例: Database)"]
end
subgraph resources["外部リソース"]
github[("GitHub<br/>リポジトリ")]
slack[("Slack<br/>メッセージ")]
db[("PostgreSQL<br/>データベース")]
end
client <-->|"プロトコル通信"| server1
client <-->|"プロトコル通信"| server2
client <-->|"プロトコル通信"| server3
server1 <-->|"API/接続"| github
server2 <-->|"API/接続"| slack
server3 <-->|"API/接続"| db
この図から以下のことがわかります。
- MCP ホスト: Claude Desktop や VS Code などの AI アプリケーションが該当します
- MCP クライアント: ホスト内で動作し、サーバーとの通信を管理します
- MCP サーバー: 外部システムへの接続とデータ提供を担当します
MCP サーバーの役割と重要性
MCP サーバーは、AI アシスタントと実際のデータソースの間に立つ橋渡し役です。具体的には、以下の 3 つの主要機能を提供します。
# | 機能名 | 説明 | 具体例 |
---|---|---|---|
1 | プロンプト | LLM とのやり取りを導くテンプレート | 定型質問フォーマット |
2 | リソース | モデルに追加コンテキストを提供 | ファイル内容、DB レコード |
3 | ツール | モデルがアクションを実行可能にする | ファイル作成、API 呼び出し |
これらの機能により、AI アシスタントは単なる会話だけでなく、実際のシステムとやり取りし、タスクを実行できるようになります。
セットアップの必要性
MCP サーバーを適切にセットアップすることで、以下のメリットが得られます。
まず、AI アシスタントの能力が大幅に拡張されます。ファイルシステムへのアクセス、データベース操作、API 呼び出しなど、さまざまな操作が可能になるでしょう。
次に、標準化されたプロトコルにより、一度構築した MCP サーバーは複数の AI アプリケーションで再利用できます。
さらに、セキュリティ面でも、適切な環境変数管理と証明書設定により、安全な通信が保証されます。
課題
セットアップ時の一般的な問題点
MCP サーバーのセットアップには、いくつかの典型的な課題があります。初めて取り組む開発者が直面する問題を理解しておくことで、スムーズな構築が可能になるでしょう。
以下の図で、セットアップ時に遭遇する主な課題の流れを確認しましょう。
mermaidflowchart TD
start["MCP サーバー<br/>セットアップ開始"] --> choice1{"インストール<br/>方法の選択"}
choice1 -->|"Python"| python_issues["Python 環境の問題<br/>- バージョン不一致<br/>- 依存関係の競合"]
choice1 -->|"Node.js"| node_issues["Node.js 環境の問題<br/>- パッケージエラー<br/>- npx の実行失敗"]
python_issues --> env_config["環境変数設定"]
node_issues --> env_config
env_config --> env_issues{"環境変数の<br/>管理方法"}
env_issues -->|"直接記述"| security_risk["セキュリティリスク<br/>- API キー漏洩<br/>- 認証情報の露出"]
env_issues -->|".env ファイル"| path_issues["パス解決の問題<br/>- 相対パスエラー<br/>- ファイル読み込み失敗"]
security_risk --> transport_choice["トランスポート選択"]
path_issues --> transport_choice
transport_choice --> transport_issues{"通信方式の<br/>複雑さ"}
transport_issues -->|"STDIO"| stdio_limit["STDIO の制限<br/>- ローカルのみ対応<br/>- デバッグ困難"]
transport_issues -->|"HTTP/SSE"| port_issues["ポート設定の問題<br/>- ポート競合<br/>- ファイアウォール"]
stdio_limit --> cert_config["証明書設定"]
port_issues --> cert_config
cert_config --> cert_issues["証明書の課題<br/>- 自己署名証明書エラー<br/>- HTTPS 必須要件<br/>- リバースプロキシ設定"]
cert_issues --> task_end["トラブル<br/>シューティングが必要"]
この図から、セットアップには複数の段階があり、各段階で固有の課題が発生することがわかります。
環境変数管理の難しさ
API キーやアクセストークンなど、機密情報の管理は特に注意が必要です。
よくある失敗例として、設定ファイルに直接 API キーを記述してしまい、誤ってリポジトリにコミットしてしまうケースがあります。また、環境変数のパス解決が正しく行われず、サーバーが起動時に必要な認証情報を読み込めないこともあるでしょう。
さらに、開発環境と本番環境で異なる環境変数を管理する必要があり、その切り替えが煩雑になりがちです。
トランスポート選択の複雑さ
MCP は複数のトランスポート方式をサポートしていますが、それぞれに特性と制約があります。
STDIO(標準入出力)は最もシンプルですが、ローカル環境でのみ動作します。リモート接続が必要な場合は、SSE(Server-Sent Events)か Streamable HTTP を選択する必要がありますが、これらはポート設定やネットワーク設定が必要になります。
どのトランスポートを選ぶべきか、そしてそれぞれの設定方法を理解することが、セットアップの重要なステップとなるでしょう。
証明書設定とセキュリティの課題
リモート接続を行う MCP サーバーでは、HTTPS による安全な通信が必須です。
しかし、ローカル開発環境で自己署名証明書を使用すると、SSL 証明書検証エラーが発生します。本番環境では信頼できる証明書を使用する必要がありますが、その取得と設定には手間がかかります。
さらに、Docker コンテナ内で MCP サーバーを実行する場合、リバースプロキシ(NGINX など)の設定が不可欠になるケースも多いでしょう。
解決策
インストール手順
MCP サーバーのインストールは、使用する言語環境によって手順が異なります。ここでは、Python と Node.js の両方の環境について、段階的に解説します。
前提条件の確認
まず、システムに必要なツールがインストールされているか確認しましょう。
Python 環境の場合
Python 3.10 以上が必要です。バージョンを確認するには、以下のコマンドを実行します。
bashpython3 --version
Node.js 環境の場合
Node.js 16 以上が推奨されます。バージョンを確認するには、以下のコマンドを実行します。
bashnode --version
Python 環境でのインストール
Python で MCP サーバーを構築する場合、uv
または pip
を使用します。
uv を使用する方法(推奨)
uv
は高速な Python パッケージマネージャーです。macOS では Homebrew でインストールできます。
bashbrew install uv
インストール後、バージョンを確認します。
bashuv --version
MCP サーバーのインストールは、以下のコマンドで実行します。
bash# プロジェクトディレクトリに移動
cd your-mcp-server-project
# 依存関係をインストール
uv pip install mcp httpx fastapi uvicorn
pip を使用する方法
従来の pip
を使用する場合は、仮想環境を作成してからインストールします。
bash# 仮想環境を作成
python3 -m venv venv
# 仮想環境を有効化(macOS/Linux)
source venv/bin/activate
# 仮想環境を有効化(Windows)
venv\Scripts\activate
仮想環境を有効化したら、必要なパッケージをインストールします。
bashpip install mcp httpx fastapi uvicorn
Node.js 環境でのインストール
Node.js で MCP サーバーを構築する場合、Yarn または npm を使用します。
Yarn を使用する方法(推奨)
Yarn がインストールされていない場合は、まずインストールします。
bashnpm install -g yarn
MCP サーバーの依存関係をインストールします。
bash# プロジェクトディレクトリに移動
cd your-mcp-server-project
# 依存関係をインストール
yarn add @modelcontextprotocol/sdk
npm を使用する方法
npm を使用する場合は、以下のコマンドでインストールします。
bashnpm install @modelcontextprotocol/sdk
設定ファイルの配置
MCP サーバーを使用するには、設定ファイルを適切な場所に配置する必要があります。設定ファイルの場所は、使用するアプリケーションと OS によって異なります。
Claude Desktop の場合
Claude Desktop の設定ファイル名は claude_desktop_config.json
です。
# | OS | 設定ファイルのパス |
---|---|---|
1 | macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
2 | Windows | %APPDATA%\Claude\claude_desktop_config.json |
3 | Linux | ~/.config/Claude/claude_desktop_config.json |
Claude Code(VS Code 拡張機能)の場合
Claude Code では、プロジェクトルートまたはユーザーディレクトリに設定ファイルを配置します。
# | スコープ | 設定ファイルのパス |
---|---|---|
1 | プロジェクト | .claude/mcp.json |
2 | ユーザー | ~/.claude/mcp.json |
設定ファイルの基本構造は、以下のようになります。
json{
"mcpServers": {
"server-name": {
"command": "node",
"args": ["path/to/server.js"]
}
}
}
この基本構造に、環境変数やトランスポート設定を追加していきます。
環境変数設定
環境変数は、API キーやデータベース接続情報など、機密情報を安全に管理するために不可欠です。MCP サーバーでは、複数の方法で環境変数を設定できます。
env フィールドでの直接指定
最もシンプルな方法は、設定ファイルの env
フィールドに直接環境変数を指定することです。
設定ファイル(claude_desktop_config.json
または .claude/mcp.json
)に、以下のように記述します。
json{
"mcpServers": {
"github-server": {
"command": "node",
"args": ["path/to/github-server.js"],
"env": {
"GITHUB_TOKEN": "ghp_your_token_here",
"DEBUG": "true",
"LOG_LEVEL": "info"
}
}
}
}
この方法のメリットは、設定が一箇所にまとまり、わかりやすいことです。ただし、設定ファイルを Git にコミットする場合は、機密情報が含まれないよう注意が必要です。
envfile プロパティの使用
より安全な方法として、.env
ファイルを別途作成し、envfile
プロパティで参照する方法があります。
まず、プロジェクトディレクトリに .env
ファイルを作成します。
bash# .env ファイル
GITHUB_TOKEN=ghp_your_token_here
SLACK_TOKEN=xoxb-your-slack-token
DATABASE_URL=postgresql://user:pass@localhost:5432/dbname
DEBUG=true
次に、設定ファイルで .env
ファイルのパスを指定します。
json{
"mcpServers": {
"github-server": {
"command": "node",
"args": ["path/to/github-server.js"],
"envfile": "${workspaceFolder}/.env"
}
}
}
.env
ファイルは .gitignore
に追加することで、Git リポジトリにコミットされるのを防げます。
bash# .gitignore に追加
.env
.env.local
.env.*.local
環境変数の展開構文
Claude Code は、柔軟な環境変数展開構文をサポートしています。これにより、デフォルト値の設定や、システム環境変数の参照が可能になります。
デフォルト値の設定
環境変数が設定されていない場合のデフォルト値を指定できます。
json{
"mcpServers": {
"api-server": {
"command": "node",
"args": ["server.js"],
"env": {
"API_PORT": "${API_PORT:-8080}",
"LOG_LEVEL": "${LOG_LEVEL:-info}",
"NODE_ENV": "${NODE_ENV:-development}"
}
}
}
}
この例では、API_PORT
が設定されていない場合は 8080
が、LOG_LEVEL
が設定されていない場合は info
が使用されます。
システム環境変数の参照
システムに既に設定されている環境変数を参照することもできます。
json{
"mcpServers": {
"home-server": {
"command": "python3",
"args": ["${HOME}/mcp-servers/server.py"],
"env": {
"USER_HOME": "${HOME}",
"PATH": "${PATH}"
}
}
}
}
環境別の設定管理
開発環境、ステージング環境、本番環境で異なる環境変数を使用する場合の管理方法です。
環境ごとに .env
ファイルを作成します。
bash# 開発環境
.env.development
# ステージング環境
.env.staging
# 本番環境
.env.production
設定ファイルでは、環境変数 NODE_ENV
に基づいて適切なファイルを読み込むように設定します。
json{
"mcpServers": {
"api-server": {
"command": "node",
"args": ["server.js"],
"envfile": "${workspaceFolder}/.env.${NODE_ENV:-development}"
}
}
}
Python での環境変数の取得
Python で MCP サーバーを実装する場合、環境変数を取得する方法は以下の通りです。
pythonimport os
# 環境変数を取得(存在しない場合は None)
github_token = os.getenv("GITHUB_TOKEN")
# デフォルト値を指定して取得
api_port = os.getenv("API_PORT", "8080")
log_level = os.getenv("LOG_LEVEL", "info")
python-dotenv
ライブラリを使用すると、.env
ファイルの読み込みが簡単になります。
pythonfrom dotenv import load_dotenv
import os
# .env ファイルを読み込む
load_dotenv()
# 環境変数を取得
github_token = os.getenv("GITHUB_TOKEN")
database_url = os.getenv("DATABASE_URL")
Node.js/TypeScript での環境変数の取得
Node.js または TypeScript で MCP サーバーを実装する場合、環境変数は process.env
でアクセスします。
typescript// 環境変数を取得
const githubToken = process.env.GITHUB_TOKEN;
const apiPort = process.env.API_PORT || '8080';
const logLevel = process.env.LOG_LEVEL || 'info';
dotenv
パッケージを使用すると、.env
ファイルを読み込めます。
typescriptimport dotenv from 'dotenv';
// .env ファイルを読み込む
dotenv.config();
// 環境変数を取得
const githubToken = process.env.GITHUB_TOKEN;
const slackToken = process.env.SLACK_TOKEN;
Deno での環境変数の取得
Deno で MCP サーバーを実装する場合は、Deno.env.get()
を使用します。
typescript// 環境変数を取得
const githubToken = Deno.env.get('GITHUB_TOKEN');
const apiPort = Deno.env.get('API_PORT') || '8080';
Deno は、実行時に --allow-env
フラグが必要です。
bashdeno run --allow-env server.ts
ポート設定とトランスポートの選択
MCP サーバーは、複数のトランスポート方式をサポートしています。それぞれの特性を理解し、用途に応じて適切なものを選択することが重要です。
以下の表で、各トランスポートの特徴を比較しましょう。
# | トランスポート | 通信方式 | ポート | 用途 | メリット | デメリット |
---|---|---|---|---|---|---|
1 | STDIO | 標準入出力 | 不要 | ローカル開発 | 設定が簡単、デバッグしやすい | リモート接続不可 |
2 | SSE | HTTP + SSE | 必要(デフォルト: 8080) | リモート接続(レガシー) | 一方向ストリーミング | HTTP POST との組み合わせが必要 |
3 | Streamable HTTP | HTTP ストリーミング | 必要 | 本番環境 | 双方向ストリーミング、効率的 | 設定がやや複雑 |
STDIO トランスポート
STDIO(Standard Input/Output)は、最もシンプルなトランスポート方式です。ローカルで動作するプロセス間通信に使用されます。
Python での STDIO サーバーの実装
FastMCP を使用した STDIO サーバーの基本的な実装です。
pythonfrom fastmcp import FastMCP
# MCP サーバーのインスタンスを作成
mcp = FastMCP("My MCP Server")
# ツールを定義
@mcp.tool()
def hello(name: str) -> str:
"""ユーザーに挨拶します"""
return f"こんにちは、{name}さん!"
サーバーのメイン処理を記述します。デフォルトでは STDIO トランスポートが使用されます。
pythonif __name__ == "__main__":
# STDIO トランスポートで実行(デフォルト)
mcp.run()
Node.js/TypeScript での STDIO サーバーの実装
MCP SDK を使用した STDIO サーバーの実装です。
typescriptimport { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
// サーバーインスタンスを作成
const server = new Server(
{
name: 'my-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
ツールハンドラーを登録し、トランスポートを初期化します。
typescript// ツールハンドラーを登録
server.setRequestHandler('tools/call', async (request) => {
// ツールの実装
});
// STDIO トランスポートで起動
const transport = new StdioServerTransport();
await server.connect(transport);
STDIO サーバーの設定
Claude Desktop または Claude Code の設定ファイルで STDIO サーバーを登録します。
json{
"mcpServers": {
"my-stdio-server": {
"command": "python3",
"args": ["/path/to/server.py"]
}
}
}
Node.js サーバーの場合は、以下のように設定します。
json{
"mcpServers": {
"my-stdio-server": {
"command": "node",
"args": ["/path/to/server.js"]
}
}
}
Windows 環境で npx
を使用する場合は、cmd /c
ラッパーが必要です。
json{
"mcpServers": {
"my-stdio-server": {
"command": "cmd",
"args": ["/c", "npx", "-y", "@some/mcp-package"]
}
}
}
SSE(Server-Sent Events)トランスポート
SSE トランスポートは、HTTP ベースのリモート接続を可能にします。サーバーからクライアントへは SSE、クライアントからサーバーへは HTTP POST を使用します。
Python での SSE サーバーの実装
FastMCP で SSE トランスポートを使用する場合、run()
メソッドにパラメータを指定します。
pythonfrom fastmcp import FastMCP
mcp = FastMCP("My SSE Server")
@mcp.tool()
def get_data(query: str) -> dict:
"""データを取得します"""
return {"result": f"Query: {query}"}
SSE トランスポートで起動するには、ホストとポートを指定します。
pythonif __name__ == "__main__":
# SSE トランスポートで起動
mcp.run(
transport="sse",
host="127.0.0.1",
port=8000
)
カスタムエンドポイントパスを指定することもできます。
pythonif __name__ == "__main__":
mcp.run(
transport="sse",
host="0.0.0.0",
port=8080,
sse_path="/sse",
message_path="/messages"
)
SSE サーバーの設定
Claude Code で SSE サーバーを登録するには、claude mcp add
コマンドを使用します。
bashclaude mcp add --transport sse my-sse-server http://localhost:8000
設定ファイルに直接記述する場合は、以下のようになります。
json{
"mcpServers": {
"my-sse-server": {
"transport": "sse",
"url": "http://localhost:8000/sse"
}
}
}
Streamable HTTP トランスポート
Streamable HTTP は、本番環境での使用に推奨される、最も効率的なトランスポート方式です。双方向ストリーミングをサポートします。
HTTP サーバーの設定
Claude Code で HTTP サーバーを登録します。
bashclaude mcp add --transport http my-http-server https://api.example.com/mcp
認証ヘッダーを含める場合は、以下のように設定します。
json{
"mcpServers": {
"my-http-server": {
"transport": "http",
"url": "https://api.example.com/mcp",
"headers": {
"Authorization": "Bearer ${API_TOKEN}",
"X-API-Key": "${API_KEY}"
}
}
}
}
ポート競合の解決
複数の MCP サーバーを同時に実行する場合、ポート競合が発生する可能性があります。
使用中のポートを確認するには、以下のコマンドを使用します。
bash# macOS/Linux
lsof -i :8080
# Windows
netstat -ano | findstr :8080
各サーバーに異なるポートを割り当てることで、競合を回避できます。
json{
"mcpServers": {
"server-a": {
"transport": "sse",
"url": "http://localhost:8000/sse"
},
"server-b": {
"transport": "sse",
"url": "http://localhost:8001/sse"
},
"server-c": {
"transport": "sse",
"url": "http://localhost:8002/sse"
}
}
}
STDIO サーバーを SSE として公開する
ローカルの STDIO サーバーをリモートから利用可能にするため、mcp-proxy
ツールを使用できます。
mcp-proxy
をインストールします。
bashyarn global add mcp-proxy
STDIO サーバーを SSE エンドポイントとして公開します。
bashmcp-proxy --port=8080 uvx mcp-server-fetch
これにより、ローカルの STDIO サーバーが http://localhost:8080
で SSE サーバーとして利用可能になります。
証明書設定とセキュリティ
リモート接続を行う MCP サーバー(SSE や Streamable HTTP)では、HTTPS による安全な通信が必須です。適切な証明書設定により、データの盗聴や改ざんを防ぐことができます。
以下の図で、証明書設定の全体フローを確認しましょう。
mermaidflowchart TD
start["証明書設定開始"] --> env_check{"環境の確認"}
env_check -->|"ローカル開発"| local_dev["ローカル開発環境"]
env_check -->|"本番環境"| production["本番環境"]
local_dev --> mkcert_check{"mkcert を<br/>使用可能?"}
mkcert_check -->|"はい"| mkcert_install["mkcert のインストール"]
mkcert_check -->|"いいえ"| self_signed["自己署名証明書を作成"]
mkcert_install --> mkcert_cert["信頼された<br/>ローカル証明書を生成"]
self_signed --> trust_cert["証明書を信頼リストに追加"]
mkcert_cert --> local_config["サーバー設定に<br/>証明書パスを追加"]
trust_cert --> local_config
production --> cert_source{"証明書の取得元"}
cert_source -->|"Let's Encrypt"| letsencrypt["certbot で<br/>無料証明書を取得"]
cert_source -->|"商用 CA"| commercial_ca["CA から証明書を購入"]
cert_source -->|"クラウドサービス"| cloud_cert["AWS ACM/GCP<br/>証明書マネージャー"]
letsencrypt --> reverse_proxy["リバースプロキシ設定"]
commercial_ca --> reverse_proxy
cloud_cert --> reverse_proxy
reverse_proxy --> nginx_config["NGINX で<br/>TLS ターミネーション"]
nginx_config --> security_headers["セキュリティヘッダー設定"]
local_config --> test_connection["HTTPS 接続テスト"]
security_headers --> test_connection
test_connection --> task_end["証明書設定完了"]
この図から、ローカル開発と本番環境で異なるアプローチが必要であることがわかります。
ローカル開発環境での証明書設定
ローカル開発では、mkcert
を使用することで、信頼された証明書を簡単に生成できます。
mkcert のインストール
macOS では Homebrew でインストールできます。
bashbrew install mkcert
Linux では、以下のコマンドでインストールします。
bash# Ubuntu/Debian
sudo apt install mkcert
# Arch Linux
sudo pacman -S mkcert
Windows では、Chocolatey または Scoop を使用します。
bash# Chocolatey
choco install mkcert
# Scoop
scoop install mkcert
ローカル CA のインストール
mkcert
のルート証明書をシステムにインストールします。
bashmkcert -install
このコマンドにより、mkcert
が生成する証明書が自動的に信頼されるようになります。
証明書の生成
ローカルホスト用の証明書を生成します。
bash# localhost 用の証明書を生成
mkcert localhost 127.0.0.1 ::1
このコマンドにより、localhost.pem
(証明書)と localhost-key.pem
(秘密鍵)が生成されます。
複数のドメイン名に対応する証明書も生成できます。
bashmkcert localhost 127.0.0.1 myapp.local "*.myapp.local"
Python サーバーでの証明書使用
FastMCP で HTTPS を有効にするには、証明書と秘密鍵のパスを指定します。
pythonfrom fastmcp import FastMCP
mcp = FastMCP("My Secure Server")
@mcp.tool()
def secure_operation(data: str) -> dict:
"""セキュアな操作を実行"""
return {"status": "success", "data": data}
SSE トランスポートで HTTPS を有効にして起動します。
pythonif __name__ == "__main__":
mcp.run(
transport="sse",
host="127.0.0.1",
port=8443,
ssl_certfile="./localhost.pem",
ssl_keyfile="./localhost-key.pem"
)
Node.js サーバーでの証明書使用
Node.js の https
モジュールで証明書を使用します。
typescriptimport https from 'https';
import fs from 'fs';
import express from 'express';
const app = express();
// HTTPS サーバーオプション
const httpsOptions = {
cert: fs.readFileSync('./localhost.pem'),
key: fs.readFileSync('./localhost-key.pem'),
};
HTTPS サーバーを起動します。
typescript// HTTPS サーバーを作成
const server = https.createServer(httpsOptions, app);
server.listen(8443, () => {
console.log(
'HTTPS サーバーが起動しました: https://localhost:8443'
);
});
自己署名証明書の作成と使用
mkcert
を使用できない環境では、OpenSSL で自己署名証明書を作成できます。
OpenSSL による証明書生成
秘密鍵と証明書を一度に生成します。
bashopenssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
-days 365 -nodes \
-subj "/C=JP/ST=Tokyo/L=Tokyo/O=MyOrg/CN=localhost"
このコマンドで、key.pem
(秘密鍵)と cert.pem
(証明書)が生成されます。
自己署名証明書の信頼設定
macOS で自己署名証明書を信頼リストに追加します。
bashsudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain cert.pem
自己署名証明書使用時の注意点
自己署名証明書を使用する場合、クライアント側で証明書検証エラーが発生します。開発環境では、検証を無効にするオプションがある場合がありますが、本番環境では絶対に使用しないでください。
本番環境での証明書設定
本番環境では、信頼できる認証局(CA)から取得した証明書を使用する必要があります。
Let's Encrypt を使用した無料証明書の取得
Let's Encrypt は、無料で信頼された SSL/TLS 証明書を提供するサービスです。
certbot
をインストールします。
bash# Ubuntu/Debian
sudo apt install certbot
# macOS
brew install certbot
証明書を取得します(standalone モード)。
bashsudo certbot certonly --standalone -d yourdomain.com
証明書は /etc/letsencrypt/live/yourdomain.com/
に保存されます。
証明書の自動更新設定
Let's Encrypt の証明書は 90 日間有効です。自動更新を設定しておきましょう。
bash# 更新のテスト
sudo certbot renew --dry-run
# 自動更新の設定(cron)
sudo crontab -e
cron に以下を追加します。
bash0 0 * * * certbot renew --quiet
リバースプロキシ(NGINX)の設定
本番環境、特に Docker コンテナで MCP サーバーを実行する場合、NGINX をリバースプロキシとして使用することが推奨されます。
NGINX のインストール
bash# Ubuntu/Debian
sudo apt install nginx
# macOS
brew install nginx
NGINX 設定ファイルの作成
/etc/nginx/sites-available/mcp-server
に設定ファイルを作成します。
nginxserver {
listen 443 ssl http2;
server_name yourdomain.com;
# SSL 証明書の設定
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# SSL プロトコルと暗号スイートの設定
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
プロキシ設定とセキュリティヘッダーを追加します。
nginx # MCP サーバーへのプロキシ設定
location /mcp {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
SSE エンドポイント用の特別な設定を追加します。
nginx # SSE エンドポイント用設定(圧縮を無効化)
location /sse {
proxy_pass http://localhost:8080/sse;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding off;
}
セキュリティヘッダーを設定します。
nginx # セキュリティヘッダー
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
}
HTTP から HTTPS へのリダイレクト設定を追加します。
nginx# HTTP を HTTPS にリダイレクト
server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}
NGINX 設定の有効化と再起動
設定ファイルをシンボリックリンクで有効化します。
bashsudo ln -s /etc/nginx/sites-available/mcp-server /etc/nginx/sites-enabled/
設定ファイルの構文をチェックします。
bashsudo nginx -t
NGINX を再起動します。
bashsudo systemctl restart nginx
Docker 環境での証明書設定
Docker コンテナで MCP サーバーを実行する場合、docker-compose
を使用して NGINX と連携させます。
docker-compose.yml の例
yamlversion: '3.8'
services:
mcp-server:
build: ./mcp-server
ports:
- '8080:8080'
environment:
- NODE_ENV=production
networks:
- mcp-network
nginx:
image: nginx:alpine
ports:
- '443:443'
- '80:80'
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- /etc/letsencrypt:/etc/letsencrypt:ro
depends_on:
- mcp-server
networks:
- mcp-network
networks:
mcp-network:
driver: bridge
この設定により、NGINX が TLS ターミネーションを担当し、バックエンドの MCP サーバーは HTTP で通信します。
証明書のトラブルシューティング
証明書設定でよく発生する問題と解決方法です。
SSL 証明書検証エラー
エラーメッセージ: SSL certificate verification failed
原因は、自己署名証明書を使用している、または証明書チェーンが不完全であることが考えられます。
解決方法として、Let's Encrypt の fullchain.pem
を使用するか、中間証明書を含める必要があります。
bash# 証明書チェーンの確認
openssl s_client -connect yourdomain.com:443 -showcerts
証明書の期限切れ
Let's Encrypt の証明書は 90 日で期限切れになります。自動更新が正しく設定されているか確認しましょう。
bash# 証明書の有効期限を確認
sudo certbot certificates
ポート 443 へのアクセス不可
ファイアウォールで HTTPS ポート(443)が開いているか確認します。
bash# Ubuntu/Debian
sudo ufw allow 443/tcp
# CentOS/RHEL
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
具体例
ここまでの解説を踏まえて、実際の MCP サーバーセットアップの完全な実装例を示します。Claude Desktop と Claude Code の両方で使用できる、実用的な構成です。
全体のセットアップワークフロー
まず、セットアップ全体の流れを図で確認しましょう。
mermaidflowchart TD
start["セットアップ開始"] --> install["環境のインストール"];
install --> lang_choice{"言語環境の選択"};
lang_choice --|Python|--> python_setup["Python + uv<br/>のセットアップ"];
lang_choice --|Node.js|--> node_setup["Node.js + Yarn<br/>のセットアップ"];
python_setup --> create_server["MCP サーバーの実装"];
node_setup --> create_server;
create_server --> env_setup["環境変数の設定"];
env_setup --> env_file["`.env` ファイルの作成"];
env_file --> config_file["設定ファイルの作成"];
config_file --> transport_choice{"トランスポートの選択"};
transport_choice --|ローカル開発|--> stdio_config["STDIO 設定"];
transport_choice --|リモート接続|--> remote_config["SSE/HTTP 設定"];
stdio_config --> test_local["ローカルテスト"];
remote_config --> cert_setup["証明書設定"];
cert_setup --> dev_cert{"開発環境?"};
dev_cert --|はい|--> mkcert_setup["mkcert で証明書生成"];
dev_cert --|いいえ|--> prod_cert["Let's Encrypt 証明書"];
mkcert_setup --> https_config["HTTPS サーバー起動"];
prod_cert --> nginx_setup["NGINX リバースプロキシ"];
nginx_setup --> https_config;
https_config --> test_remote["リモートテスト"];
test_local --> verify["動作確認"];
test_remote --> verify;
verify --> task_end["セットアップ完了"];
この図から、セットアップが段階的に進むことがわかります。では、具体的な実装を見ていきましょう。
実装例 1: GitHub 連携 MCP サーバー(Python)
GitHub API と連携する MCP サーバーの完全な実装例です。
プロジェクト構造
bashgithub-mcp-server/
├── server.py
├── .env
├── .env.example
├── .gitignore
└── requirements.txt
requirements.txt
必要なパッケージを記述します。
shellmcp>=1.0.0
httpx>=0.25.0
fastapi>=0.104.0
uvicorn>=0.24.0
python-dotenv>=1.0.0
.env.example
(テンプレート)
環境変数のテンプレートファイルを作成します。
bash# GitHub API トークン
GITHUB_TOKEN=your_github_token_here
# サーバー設定
PORT=8000
LOG_LEVEL=info
.env
(実際の設定)
実際の API キーを記述します(Git には含めない)。
bashGITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
PORT=8000
LOG_LEVEL=info
.gitignore
機密情報を含むファイルを Git から除外します。
bash.env
__pycache__/
*.pyc
.DS_Store
server.py(パート 1: インポートと初期化)
必要なモジュールをインポートします。
pythonfrom fastmcp import FastMCP
from dotenv import load_dotenv
import os
import httpx
from typing import Optional
# 環境変数を読み込む
load_dotenv()
# MCP サーバーのインスタンスを作成
mcp = FastMCP("GitHub MCP Server")
server.py(パート 2: GitHub API クライアント)
GitHub API との通信を担当するクラスを定義します。
pythonclass GitHubClient:
"""GitHub API クライアント"""
def __init__(self, token: str):
self.token = token
self.base_url = "https://api.github.com"
self.headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json"
}
async def get_repo_info(self, owner: str, repo: str) -> dict:
"""リポジトリ情報を取得"""
async with httpx.AsyncClient() as client:
response = await client.get(
f"{self.base_url}/repos/{owner}/{repo}",
headers=self.headers
)
response.raise_for_status()
return response.json()
server.py(パート 3: MCP ツールの定義)
MCP サーバーが提供するツールを定義します。
python# GitHub クライアントのインスタンスを作成
github_token = os.getenv("GITHUB_TOKEN")
if not github_token:
raise ValueError("GITHUB_TOKEN が設定されていません")
github_client = GitHubClient(github_token)
@mcp.tool()
async def get_repository(owner: str, repo: str) -> dict:
"""
GitHub リポジトリの情報を取得します
Args:
owner: リポジトリのオーナー名
repo: リポジトリ名
Returns:
リポジトリの詳細情報
"""
try:
repo_info = await github_client.get_repo_info(owner, repo)
return {
"name": repo_info["name"],
"description": repo_info["description"],
"stars": repo_info["stargazers_count"],
"forks": repo_info["forks_count"],
"language": repo_info["language"],
"url": repo_info["html_url"]
}
except Exception as e:
return {"error": str(e)}
server.py(パート 4: サーバー起動)
環境変数から設定を読み込み、サーバーを起動します。
pythonif __name__ == "__main__":
# 環境変数から設定を取得
port = int(os.getenv("PORT", "8000"))
log_level = os.getenv("LOG_LEVEL", "info")
# 開発環境では STDIO、本番環境では SSE を使用
if os.getenv("NODE_ENV") == "production":
mcp.run(
transport="sse",
host="127.0.0.1",
port=port
)
else:
# デフォルトは STDIO
mcp.run()
Claude Desktop 用設定(claude_desktop_config.json
)
macOS の場合、~/Library/Application Support/Claude/claude_desktop_config.json
を編集します。
json{
"mcpServers": {
"github-server": {
"command": "python3",
"args": [
"/absolute/path/to/github-mcp-server/server.py"
],
"envfile": "/absolute/path/to/github-mcp-server/.env"
}
}
}
Claude Code 用設定(.claude/mcp.json
)
プロジェクトルートの .claude/mcp.json
を作成します。
json{
"mcpServers": {
"github-server": {
"command": "python3",
"args": [
"${workspaceFolder}/github-mcp-server/server.py"
],
"envfile": "${workspaceFolder}/github-mcp-server/.env"
}
}
}
実装例 2: Slack 連携 MCP サーバー(Node.js/TypeScript)
Slack API と連携する MCP サーバーの実装例です。
プロジェクト構造
bashslack-mcp-server/
├── src/
│ └── index.ts
├── .env
├── .env.example
├── .gitignore
├── package.json
└── tsconfig.json
package.json
依存パッケージを定義します。
json{
"name": "slack-mcp-server",
"version": "1.0.0",
"type": "module",
"scripts": {
"build": "tsc",
"dev": "tsx src/index.ts",
"start": "node dist/index.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.0.0",
"@slack/web-api": "^6.9.0",
"dotenv": "^16.3.1"
},
"devDependencies": {
"@types/node": "^20.10.0",
"tsx": "^4.7.0",
"typescript": "^5.3.0"
}
}
tsconfig.json
TypeScript の設定を記述します。
json{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "node",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
.env.example
環境変数のテンプレートです。
bashSLACK_TOKEN=xoxb-your-slack-bot-token
PORT=8000
NODE_ENV=development
src/index.ts
(パート 1: インポートと初期化)
必要なモジュールをインポートし、初期化します。
typescriptimport { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { WebClient } from '@slack/web-api';
import dotenv from 'dotenv';
// 環境変数を読み込む
dotenv.config();
// Slack クライアントの初期化
const slackToken = process.env.SLACK_TOKEN;
if (!slackToken) {
throw new Error('SLACK_TOKEN が設定されていません');
}
const slackClient = new WebClient(slackToken);
src/index.ts
(パート 2: MCP サーバーの作成)
MCP サーバーのインスタンスを作成し、機能を定義します。
typescript// MCP サーバーのインスタンスを作成
const server = new Server(
{
name: 'slack-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
src/index.ts
(パート 3: ツールハンドラーの実装)
Slack メッセージ送信ツールを実装します。
typescript// ツールハンドラーを登録
server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params;
if (name === 'send_message') {
try {
// Slack にメッセージを送信
const result = await slackClient.chat.postMessage({
channel: args.channel,
text: args.text,
});
return {
content: [
{
type: 'text',
text: JSON.stringify({
success: true,
timestamp: result.ts,
channel: result.channel,
}),
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: JSON.stringify({
success: false,
error: error.message,
}),
},
],
isError: true,
};
}
}
throw new Error(`未知のツール: ${name}`);
});
src/index.ts
(パート 4: サーバー起動)
トランスポートを初期化し、サーバーを起動します。
typescript// STDIO トランスポートで起動
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('Slack MCP Server が起動しました');
}
main().catch((error) => {
console.error('サーバー起動エラー:', error);
process.exit(1);
});
Claude Code 用設定(claude mcp add
コマンド)
Claude Code CLI を使用して MCP サーバーを登録します。
bash# STDIO トランスポートで登録
claude mcp add --transport stdio slack-server \
--env SLACK_TOKEN="${SLACK_TOKEN}" \
-- yarn tsx src/index.ts
実装例 3: HTTPS 対応リモート MCP サーバー
リモートアクセス可能な、HTTPS で保護された MCP サーバーの実装例です。
mkcert による証明書生成
ローカル開発用の証明書を生成します。
bash# mkcert のインストール(macOS)
brew install mkcert
# ルート CA をインストール
mkcert -install
# localhost 用の証明書を生成
mkcert localhost 127.0.0.1
これにより、localhost.pem
と localhost-key.pem
が生成されます。
HTTPS 対応 Python サーバー
先ほどの GitHub MCP サーバーを HTTPS 対応にします。
python# server.py の最後の部分を以下に変更
if __name__ == "__main__":
port = int(os.getenv("PORT", "8443"))
# HTTPS で SSE サーバーを起動
mcp.run(
transport="sse",
host="0.0.0.0",
port=port,
ssl_certfile="./localhost.pem",
ssl_keyfile="./localhost-key.pem"
)
Claude Code での HTTPS サーバー登録
HTTPS エンドポイントとして登録します。
bashclaude mcp add --transport sse github-https \
https://localhost:8443/sse
トラブルシューティング
実際の運用で発生しやすい問題と解決方法をまとめます。
問題 1: サーバーが起動しない
エラーコード: ModuleNotFoundError: No module named 'mcp'
原因として、必要なパッケージがインストールされていないことが考えられます。
解決方法は、依存パッケージを再インストールすることです。
bash# Python の場合
pip install -r requirements.txt
# Node.js の場合
yarn install
問題 2: 環境変数が読み込まれない
エラーメッセージ: GITHUB_TOKEN が設定されていません
原因は、.env
ファイルのパスが正しくない、または環境変数の名前が間違っていることです。
解決方法として、まず .env
ファイルが存在するか確認します。
bashls -la .env
次に、設定ファイルのパスが絶対パスになっているか確認します。
json{
"envfile": "/absolute/path/to/.env"
}
問題 3: ポート競合
エラーコード: Error: Address already in use (errno: 98)
原因は、指定したポートが既に使用されていることです。
使用中のポートを確認します。
bashlsof -i :8000
別のポートを使用するか、競合しているプロセスを停止します。
bash# プロセスを停止(PID を確認してから)
kill -9 <PID>
問題 4: SSL 証明書エラー
エラーメッセージ: SSL certificate verification failed
原因は、自己署名証明書が信頼されていない、または証明書の有効期限が切れていることです。
mkcert を使用している場合、ルート CA が正しくインストールされているか確認します。
bashmkcert -install
証明書の有効期限を確認します。
bashopenssl x509 -in localhost.pem -text -noout | grep "Not After"
まとめ
MCP サーバーのセットアップは、複数の段階を経て完成します。本記事で解説した手順をまとめます。
セットアップの 5 つの重要ステップ
# | ステップ | 重要ポイント | 推奨ツール |
---|---|---|---|
1 | インストール | Python 3.10+ または Node.js 16+ が必要 | uv, Yarn |
2 | 環境変数設定 | .env ファイルで機密情報を管理 | dotenv, envfile |
3 | トランスポート選択 | ローカルは STDIO、リモートは Streamable HTTP | - |
4 | 証明書設定 | 開発環境は mkcert、本番環境は Let's Encrypt | mkcert, certbot |
5 | セキュリティ対策 | NGINX でリバースプロキシと TLS ターミネーション | NGINX |
ベストプラクティス
適切な MCP サーバー運用のために、以下のベストプラクティスを守りましょう。
まず、環境変数管理についてです。API キーやトークンは必ず .env
ファイルで管理し、.gitignore
に追加してリポジトリに含めないようにします。環境ごと(開発・ステージング・本番)に異なる .env
ファイルを用意することも重要です。
次に、トランスポートの選択です。ローカル開発では STDIO を使用し、シンプルに保ちます。リモートアクセスが必要な本番環境では、Streamable HTTP を選択し、効率的な通信を実現しましょう。
証明書管理では、ローカル開発に mkcert を使用することで、信頼された証明書を簡単に生成できます。本番環境では Let's Encrypt で無料の信頼された証明書を取得し、自動更新を設定しておくことが大切です。
セキュリティ対策として、本番環境では NGINX をリバースプロキシとして使用し、TLS ターミネーションを行います。適切なセキュリティヘッダー(HSTS、X-Frame-Options など)を設定することも忘れないようにしましょう。
セキュリティ上の注意事項
MCP サーバーのセキュリティは、以下の点に特に注意が必要です。
機密情報の取り扱いでは、API キーやトークンを設定ファイルに直接記述しないこと、チャット履歴に機密情報を含めないことが重要です。
通信の保護では、リモート接続では必ず HTTPS を使用し、自己署名証明書は開発環境のみで使用することを徹底しましょう。
アクセス制御として、MCP サーバーには必要最小限の権限のみを付与し、本番環境では適切なファイアウォール設定を行うことが求められます。
次のステップ
MCP サーバーの基本的なセットアップができたら、以下のステップに進むことができます。
カスタム MCP サーバーの開発では、独自のビジネスロジックを組み込んだ MCP サーバーを構築できます。複数のツールやリソースを組み合わせた高度な機能も実装可能です。
スケーラビリティの向上では、Docker コンテナ化により複数インスタンスの管理が容易になります。Kubernetes でのオーケストレーションも検討できるでしょう。
モニタリングと監視では、ログ集約システム(ELK スタックなど)の導入や、メトリクス収集(Prometheus、Grafana など)により、サーバーの健全性を監視できます。
本記事で解説した手順に従えば、初心者でも確実に MCP サーバーをセットアップできます。ぜひ、実際に手を動かして、AI アシスタントと外部システムを連携させる素晴らしい体験を味わってください。
関連リンク
公式ドキュメント
- Model Context Protocol 公式サイト
- MCP Specification
- Model Context Protocol - GitHub
- MCP Servers リポジトリ
- Claude Code MCP ドキュメント
SDK とツール
セキュリティと証明書
参考記事
- article
MCP サーバー セットアップ完全ガイド:インストール・環境変数・ポート/証明書設定の最短手順
- article
MCP サーバー とは?Model Context Protocol の基礎・仕組み・活用メリットを徹底解説
- article
Playwright MCP で複数プロジェクトのテストを一元管理
- article
Playwright MCP 活用事例集:現場で効く業務効率化テクニック
- article
Playwright MCP とローカル実行のベンチマーク徹底比較
- article
Playwright MCP のセキュリティ対策と認証フロー
- article
NestJS クリーンアーキテクチャ:UseCase/Domain/Adapter を疎結合に保つ設計術
- article
WebSocket プロトコル設計:バージョン交渉・機能フラグ・後方互換のパターン
- article
MySQL 読み書き分離設計:ProxySQL で一貫性とスループットを両立
- article
Motion(旧 Framer Motion)アニメオーケストレーション設計:timeline・遅延・相互依存の整理術
- article
WebRTC で遠隔支援:画面注釈・ポインタ共有・低遅延音声の実装事例
- article
JavaScript パフォーマンス最適化大全:レイアウトスラッシングを潰す実践テク
- blog
iPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
- blog
Googleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
- blog
【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
- blog
Googleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
- blog
Pixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
- blog
フロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来