MCP サーバーの設定で詰まっている人の話を聞くと、大体「設定したのに認識されない」「起動直後は動くのにしばらくすると切れる」「特定のツールだけ呼び出せない」という3つのパターンに集約されます。そして多くの場合、問題の原因は表面上のエラーメッセージが示す場所とは別のところにあります。
このガイドでは、MCP 接続トラブルを根本から診断するための手順を体系的にまとめました。
MCP の仕組みを最初に押さえる
診断の前に、Claude Code と MCP サーバーがどのように通信するかを理解しておくと、エラーの原因を絞りやすくなります。
MCP(Model Context Protocol)は、Claude と外部ツール・データソースを繋ぐプロトコルです。通信方式(トランスポート)は現在2種類あります。
stdio トランスポート(標準入出力)
ローカルで動くサーバー向けのデフォルト方式です。Claude Code が設定ファイルの command に書かれたプロセスを子プロセスとして起動し、stdin/stdout を通じてJSON-RPC メッセージをやりとりします。
Claude Code
↓ spawn
[MCP server process]
↑↓ stdin/stdout (JSON-RPC)
HTTP+SSE トランスポート
リモートサーバーや、長時間稼働させたい場合に使うモードです。url を設定ファイルに指定し、HTTPエンドポイントと通信します。
この違いを知っておくことで、「接続できない」エラーがプロセス起動の問題なのか、ネットワーク層の問題なのかを最初に判断できます。
診断ステップ1: 設定ファイルを確認する
まず設定ファイルの場所と内容を確認します。
# macOS
cat ~/.claude/claude_desktop_config.json
# Windows (PowerShell)
Get-Content "$env:APPDATA\Claude\claude_desktop_config.json"
# Linux
cat ~/.config/claude/claude_desktop_config.jsonよく見るミスを順番に確認していきます。
ミス1: JSON の構文エラー
人間の目には正しく見えても、末尾カンマや引用符の不一致で JSON が壊れていることがあります。
# jq でバリデーション(jq がない場合: brew install jq)
cat ~/.claude/claude_desktop_config.json | jq .
# エラー例
# parse error (Expected separator between values) at line 8jq でエラーが出たら、JSONの構文ミスです。jsonlint.com に貼り付けると何行目に問題があるか教えてくれます。
ミス2: command が解決できない
{
"mcpServers": {
"my-server": {
"command": "my-mcp-server"
}
}
}command に書いたコマンドが PATH 上に存在しないと、Claude Code はサーバーを起動できません。
# コマンドが存在するか確認
which my-mcp-server || echo "見つかりません"
# npm でグローバルインストールしたパッケージの場合
npm list -g --depth=0 | grep mcpコマンドが見つからない場合は2択です。
// 選択肢1: npx で動的実行(インストール不要)
{
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/username/"]
}
// 選択肢2: node でスクリプトを直接指定
{
"command": "node",
"args": ["/absolute/path/to/server/index.js"]
}ミス3: 環境変数が渡っていない
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "your_token_here"
}
}
}
}env フィールドを指定しないと、シェルの環境変数は MCP サーバープロセスに引き継がれません。API キーが必要なサーバーでは必須の設定です。
診断ステップ2: サーバーを手動で起動してみる
Claude Code を介さずに、ターミナルから MCP サーバーを直接起動することで、サーバー側の問題かどうかを切り分けられます。
# stdio サーバーを手動起動(filesystem の例)
npx -y @modelcontextprotocol/server-filesystem /Users/username/projects
# 起動に成功すると stdin を待ち続ける(これが正常な状態)
# エラーが出たら、そのエラーメッセージが根本原因起動してすぐ終了する場合は、サーバー側でクラッシュしています。よくある原因は以下の3つです。
1. Node.js バージョンが古い(MCP サーバーは LTS 20以上を推奨)
→ node --version で確認。古ければ nvm で更新
2. 依存パッケージが不足している
→ サーバーディレクトリで npm install
3. 指定したパスが存在しない
→ filesystem サーバーでは対象ディレクトリが実在する必要がある
診断ステップ3: ログを読む
Claude Code は MCP 通信のログを記録しています。
# macOS のログ場所
tail -f ~/Library/Logs/Claude/mcp*.log
# Linux
tail -f ~/.local/share/claude/logs/mcp*.log
# リアルタイムで新しいログを監視しながら Claude Code を操作すると原因が掴みやすいログのフォーマットはJSON-RPC形式です。重要なフィールドを読む練習をしましょう。
// サーバー初期化リクエスト(Claude → サーバー)
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {}
}
}
// サーバーからの正常な応答
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {}
},
"serverInfo": {
"name": "filesystem",
"version": "0.6.2"
}
}
}
// エラー応答(接続失敗時)
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32603,
"message": "Internal error: EACCES: permission denied, open '/restricted/path'"
}
}error フィールドが返ってきている場合、その message が実際の原因です。initialize リクエスト自体に対する応答がなければ、サーバーがそもそも起動していません。
診断ステップ4: ツールが見つからない問題
サーバー自体は起動しているのに「このツールが見つかりません」とClaudeが言う場合、ツール登録の問題です。
MCP サーバーが提供するツールを一覧で取得するには、サーバー起動後に tools/list リクエストを送る必要があります。手動で確認するなら:
# stdio サーバーに JSON-RPC を手動送信
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | npx -y @modelcontextprotocol/server-filesystem /Users/username/
# 初期化後に tools/list を送る
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | ...ツールが返ってこない、あるいは期待するツールが含まれていない場合は、サーバー側の実装を確認してください。カスタムサーバーを実装している場合は、ListToolsRequestSchema ハンドラーが正しく実装されているかを見ます。
// カスタムMCPサーバーのツール登録確認ポイント
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{ name: "my-server", version: "1.0.0" },
{ capabilities: { tools: {} } } // ← capabilities に tools を宣言しているか確認
);
// tools/list ハンドラーが実装されているか
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "my_tool",
description: "このツールは〇〇を行います",
inputSchema: {
type: "object",
properties: {
query: { type: "string", description: "検索クエリ" }
},
required: ["query"]
}
}
]
};
});
// tools/call ハンドラーも必ず実装する
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === "my_tool") {
// ツールの実際の処理
return { content: [{ type: "text", text: "結果" }] };
}
throw new Error(`Unknown tool: ${name}`);
});接続が途中で切れる問題
起動直後は動くのに、しばらくすると切れるという問題はやっかいです。主な原因は3つです。
原因1: タイムアウト設定が短い
一部の MCP サーバーや、大きなレスポンスを返す処理では、デフォルトのタイムアウトで切れることがあります。
{
"mcpServers": {
"slow-server": {
"command": "node",
"args": ["server.js"],
"timeout": 60000
}
}
}timeout を明示的に指定することでデフォルトより長くできます。
原因2: サーバープロセスが例外でクラッシュしている
予期しない例外が発生してサーバープロセス自体が終了すると、接続が切れます。
// 例外をキャッチせずに投げてしまうとプロセスが終了する
server.setRequestHandler(CallToolRequestSchema, async (request) => {
// ❌ エラーハンドリングなし
const result = await someAsyncOperation();
return { content: [{ type: "text", text: result }] };
});
// ✅ 例外をキャッチしてエラーレスポンスを返す
server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
const result = await someAsyncOperation();
return { content: [{ type: "text", text: result }] };
} catch (error) {
return {
content: [{ type: "text", text: `エラーが発生しました: ${error.message}` }],
isError: true
};
}
});原因3: プロセスのメモリ不足
長時間稼働で Node.js のヒープが枯渇することがあります。
# メモリ上限を明示的に設定して起動
NODE_OPTIONS="--max-old-space-size=512" node server.js複数サーバーを安定稼働させる設計パターン
プロジェクトで複数の MCP サーバーを使う場合、設定の管理と障害対応を考慮した設計が必要になります。
パターン1: サーバーを役割で分割する
1つのサーバーに多くの機能を詰め込むと、1つのバグが全機能に影響します。役割ごとに分割し、独立して起動・停止できる構成にしましょう。
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "~/projects"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "..." }
},
"database": {
"command": "node",
"args": ["./tools/db-server.js"],
"env": { "DATABASE_URL": "..." }
}
}
}パターン2: ヘルスチェックエンドポイントを実装する
長時間稼働するサーバーには、動作確認用のシンプルなツールを追加しておくと、問題の早期発見に役立ちます。
// ヘルスチェック用ツール
{
name: "health_check",
description: "サーバーの動作状態を確認します",
inputSchema: { type: "object", properties: {} }
}
// Claude から「health_check を実行して」と言えば即座に状態確認できるパターン3: ログをファイルに残す
stdio サーバーでは、サーバー側のエラーを stderr に書き出すと、Claude Code がログとして記録してくれます。
// MCP サーバー内でのログ出力
process.stderr.write(JSON.stringify({
level: "error",
timestamp: new Date().toISOString(),
message: "database connection failed",
error: error.message
}) + "\n");console.log は stdio サーバーでは JSON-RPC 通信と混在するため使用禁止です。デバッグ出力は必ず process.stderr に送ってください。
MCP のトラブルシューティングで時間を取られる大半は、「設定ファイルの JSON ミス」「コマンドが PATH にない」「例外をキャッチしていないサーバーコード」の3つで説明できます。この順で確認していけば、たいていの問題は30分以内に原因が見つかるはずです。
カスタムMCPサーバーを自作している場合は、まず process.stderr へのログ出力を整備することをお勧めします。「どこで何が起きているか」が見えるようになるだけで、デバッグの時間が半分以下になります。
エラーパターン1: "MCP server not found" — サーバーが見つからない
最も一般的なエラーです。MCP サーバーがシステムに正しくインストールされていないか、パスが誤っている場合に発生します。
診断方法
まず、現在利用可能な MCP サーバーの一覧を確認しましょう:
# インストール済み MCP サーバーの一覧表示
claude mcp list
# 出力例:
# Available MCP servers:
# - stdio: node /Users/user/.npm/_npx/mcp-server-stdio/bin/server.js
# - jira: python /opt/mcp-servers/jira_server.py
# - github: node /opt/mcp-servers/github/index.js実際には存在しないサーバー名を指定しようとしている場合、上記コマンドの出力に名前が表示されません。
よくある原因と解決方法
原因1: サーバーがインストールされていない
# npx ベースの MCP サーバーの場合
npm install -g @modelcontextprotocol/server-stdio
# Python 環境の MCP サーバーの場合
pip install mcp-server-jira
# その後、Claude設定ファイル(~/.claude-config.json)を確認
cat ~/.claude-config.json原因2: パスが誤っている
Claude Desktop の設定ファイルを確認します:
// ~/.claude-config.json の例(誤り)
{
"mcpServers": {
"jira": {
"command": "python",
"args": ["/wrong/path/jira_server.py"]
}
}
}
// 正しい設定例
{
"mcpServers": {
"jira": {
"command": "python",
"args": ["/opt/homebrew/lib/python3.11/site-packages/mcp_server_jira/server.py"]
}
}
}実際のパスを確認するには:
# Python パッケージの場所を確認
python -c "import mcp_server_jira; print(mcp_server_jira.__file__)"
# Node.js パッケージの場所を確認
npm root -g # グローバルパス
which node-mcp-server # コマンドの場所確認手順
# 1. サーバーが起動可能か直接テスト
python /opt/homebrew/lib/python3.11/site-packages/mcp_server_jira/server.py
# 2. 出力が以下のようなら成功
# {"jsonrpc": "2.0", "id": 1, "method": "initialize", ...}
# 3. Claude の設定を再読み込み(Claude Desktop を再起動)エラーパターン2: "Permission denied" — パーミッション拒否エラー
特に GitHub Actions などのヘッドレス環境や、VM(Cowork モード)での実行時に発生しやすいエラーです。
GitHub Actions 環境での解決方法
GitHub Actions のワークフロー内で MCP サーバーを起動しようとする場合、カレントディレクトリのパーミッションが不足していることが多いです:
# .github/workflows/claude-code.yml の例
name: Claude Code Automation
on:
push:
branches: [main]
jobs:
auto-generate-content:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# 権限を明確に付与
- name: Fix permissions
run: |
chmod +x scripts/mcp-server.js
chmod -R 755 /tmp/mcp-runtime
- name: Run Claude Code with MCP
env:
CLAUDE_API_KEY: ${{ secrets.CLAUDE_API_KEY }}
run: |
# MCP サーバーを明示的に /tmp に配置
mkdir -p /tmp/mcp-runtime
cp scripts/mcp-server.js /tmp/mcp-runtime/
chmod +x /tmp/mcp-runtime/mcp-server.js
claude code --mcp-server /tmp/mcp-runtime/mcp-server.js/permissions コマンドで確認
Claude Desktop 内で現在のプロセスが持つパーミッションを確認できます:
# Claude Desktop の入力欄で直接実行
/permissions
# 出力例:
# Current working directory: /tmp/mcp-runtime
# Process UID: 501
# Process GID: 20
# Directory permissions: drwxr-xr-x
# File permissions: -rwxr-xr-x出力で r (読取) や x (実行) が不足していれば、以下で修正:
# ディレクトリに対して読み取り・実行権限を付与
chmod -R u+rx /path/to/mcp-server
# ファイルに実行権限を付与
chmod +x /path/to/mcp-server/bin/start.sh
# 確認
ls -la /path/to/mcp-server/VM(Cowork モード)での解決方法
Cowork モード内でファイルシステムが正しく認識されていない場合:
# 1. マウント状況を確認
mount | grep -E "mcp|workspace"
# 2. ワークスペースを再選択(Cowork設定から)
# 3. Cowork VM を再起動
# 4. キャッシュをクリア
rm -rf ~/.cowork/cacheエラーパターン3: OAuth トークン失効 — 特に Jira/Atlassian MCP
Jira や GitHub などの外部サービス連携 MCP は、OAuth トークンが一定期間で失効します。
トークン失効の症状
[ERROR] OAuth token expired
[ERROR] 401 Unauthorized: Invalid credentials
トークンの更新方法
# 1. 現在のトークンを確認
cat ~/.mcp-tokens/jira.json
# 2. トークンがあれば、再認証フローを開始
claude mcp auth jira
# 3. ブラウザでログインを求められるので、認可を許可
# 4. 更新されたトークンを確認
cat ~/.mcp-tokens/jira.json
# 5. Claude Desktop を再起動より詳しい認証情報の管理については、Claude Code MCP OAuth 認証ガイド を参照してください。
エラーパターン4: タイムアウトエラー — ツール実行が遅い
MCP ツールの実行が長時間かかる場合、デフォルトのタイムアウト値を超えるとエラーが発生します。
症状と原因
[ERROR] Tool execution timeout after 30s
[ERROR] Transport closed: Server did not respond in time
タイムアウト値の変更
Claude Desktop の設定ファイルを編集:
// ~/.claude-config.json
{
"mcpServers": {
"jira": {
"command": "python",
"args": ["/opt/homebrew/lib/python3.11/site-packages/mcp_server_jira/server.py"],
"timeout": 120000 // ミリ秒単位(デフォルト: 30000 = 30秒)
}
},
"toolExecutionTimeout": 120000 // グローバルタイムアウト
}ログを確認してボトルネックを特定
# MCP サーバーのデバッグログを有効化
CLAUDE_DEBUG=mcp claude code
# stderr に詳細ログが出力される:
# [MCP] Tool invocation: search_issues
# [MCP] Elapsed: 5234ms
# [MCP] Result size: 2.3 MB結果サイズが大きい場合、ページネーションやフィルタリングでデータ量を削減することを検討してください。
エラーパターン5: "Transport closed" / 接続が途絶える
MCP サーバープロセスがクラッシュしたり、メモリ不足で強制終了した際に発生します。
症状
[ERROR] Transport closed
[ERROR] Connection lost to MCP server
サーバー stderr の確認
# 1. MCP サーバーをフォアグラウンドで起動してエラーを直接確認
python /opt/homebrew/lib/python3.11/site-packages/mcp_server_jira/server.py 2>&1
# 2. メモリ不足で落ちている場合の出力例:
# Traceback (most recent call last):
# File "/opt/...", line 45, in handle_request
# result = process_large_dataset()
# MemoryError: Unable to allocate 2.5 GiB for array
# 3. メモリ制限を設定してサーバーを再起動
# Python の場合
python -c "import resource; resource.setrlimit(resource.RLIMIT_AS, (4*1024*1024*1024, -1))" && python server.pyプロセスモニタリング
長時間の利用を想定する場合、プロセス管理ツール(supervisor など)の使用を推奨:
# supervisor をインストール
brew install supervisor
# 設定ファイルを作成
cat > /opt/homebrew/etc/supervisor.d/mcp-jira.conf << 'EOF'
[program:mcp-jira]
command=python /opt/homebrew/lib/python3.11/site-packages/mcp_server_jira/server.py
autostart=true
autorestart=true
stderr_logfile=/var/log/mcp-jira.err.log
stdout_logfile=/var/log/mcp-jira.out.log
EOF
# 起動
supervisord -c /opt/homebrew/etc/supervisord.confエラーパターン6: サイレント失敗 — エラーが表示されない
最も厄介なケースです。MCP ツールが失敗しても何もエラーメッセージが表示されず、単に結果が返されない状況です。
--mcp-debug フラグでデバッグ
# デバッグモードで詳細ログを出力
claude code --mcp-debugログ出力例:
[DEBUG] MCP Request: {
"method": "call_tool",
"params": {
"name": "search_issues",
"arguments": {
"query": "project = MYPROJ",
"limit": 100
}
}
}
[DEBUG] MCP Response (4234ms): {
"result": null,
"error": "JIRA API returned 403: Insufficient permissions"
}
ログファイルへの出力
# ログを一時ファイルに保存してから確認
claude code --mcp-debug > /tmp/claude-mcp.log 2>&1
# リアルタイムで監視
tail -f /tmp/claude-mcp.logJSON レスポンス構造の確認
stdout に正しい JSON が返されているか確認:
# MCP サーバーを直接起動して stdin から入力
echo '{"jsonrpc":"2.0","method":"call_tool","params":{"name":"search_issues","arguments":{"query":"key=MYPROJ-1"}},"id":1}' | \
python /opt/homebrew/lib/python3.11/site-packages/mcp_server_jira/server.py正常な応答:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [{"type": "text", "text": "Issue: MYPROJ-1\nTitle: ..."}]
}
}実装チェックリスト
MCP サーバーの接続トラブルを未然に防ぐためのチェックリスト:
- [ ]
claude mcp listでサーバーが表示される - [ ] 設定ファイルのパスが正しく、ファイルが実在する
- [ ] ファイルに実行権限がある (
ls -laでxが表示される) - [ ] OAuth トークンが有効(
claude mcp auth {service}で更新済み) - [ ] タイムアウト値が適切(重い処理には 60 秒以上を推奨)
- [ ]
--mcp-debugでログに異常がない - [ ] メモリ使用量が制限以内(
topで確認)
追加したサーバーが別のディレクトリで消える — スコープの取り違え
claude mcp list に出ていたサーバーが、別のプロジェクトを開いた途端に一覧から消える。設定ファイルも壊していないのに、です。これは設定ミスではなく、サーバーを登録した「スコープ」が原因であることがほとんどです。
claude mcp add には登録範囲を決める -s(--scope)があり、値は3つです。
- local(既定): 登録したそのプロジェクト内、自分だけが使える範囲。
-sを省くとここに入ります。 - project: リポジトリ直下の
.mcp.jsonに書き出され、チームで共有される範囲。リポジトリをgit cloneした人にも配られます。 - user: 自分のすべてのプロジェクトから使える範囲。
つまり claude mcp add github -- npx -y @modelcontextprotocol/server-github のようにスコープを省いて登録すると、そのディレクトリ専用になります。別フォルダで Claude Code を開けば当然見えません。「昨日まで動いていたのに」の正体はこれです。
切り分けは、まず問題が起きているそのディレクトリで claude mcp list を実行することです。出てこなければスコープ違いを疑います。
# どのスコープに登録されているか確認する
claude mcp get github
# 全プロジェクトで使いたいなら user スコープで入れ直す
claude mcp add -s user github -- npx -y @modelcontextprotocol/server-github
# チームで共有したいなら project スコープ(.mcp.json がリポジトリに生成される)
claude mcp add -s project github -- npx -y @modelcontextprotocol/server-github.mcp.json を git clone で受け取った側は、初回利用時に承認を求められます。「設定ファイルはあるのにツールが呼べない」ときは、この承認プロンプトを見落としていないか確認してください。
私自身、個人開発で複数のリポジトリを行き来しながら作業していて、同じ MCP サーバーを各所で登録し直していた時期がありました。Dolice Labs の複数ブログを横断して同じツールを使うようになってから、共通で使うものは user スコープ、そのリポジトリ固有のものだけ project スコープ、と決めてしまったところ、「消えた」と慌てることがなくなりました。スコープは障害ではなく、どこで使うかを宣言する仕組みだと捉え直すと扱いやすくなります。
全体を振り返って
MCP の接続エラーは、サーバーの可用性、パーミッション、トークン失効、タイムアウト、メモリ不足、サイレント失敗の6つのパターンに分類できます。問題に遭遇したら、まずは claude mcp list でサーバーが認識されているか確認し、次に --mcp-debug フラグでログを出力することが早期解決への近道です。登録したはずのサーバーが見えないときは、スコープの取り違えも忘れずに疑ってください。
MCP の詳細な実装方法については、Claude Code MCP サーバー実践ガイド を、認可やコネクタ設計の考え方については MCP コネクタの単一認可設計 を参照してください。