MCP Inspector
Инструменты разработчика — подробнее о Inspector
Типичные ошибки MCP серверов и их решения — коды ошибок, отладка, FAQ
MCP использует стандартные коды ошибок JSON-RPC 2.0 плюс специфичные для протокола.
| Код | Название | Описание |
|---|---|---|
-32700 | Parse error | Невалидный JSON |
-32600 | Invalid Request | Запрос не соответствует JSON-RPC |
-32601 | Method not found | Метод не существует |
-32602 | Invalid params | Неверные параметры |
-32603 | Internal error | Внутренняя ошибка сервера |
| Код | Название | Описание |
|---|---|---|
-32000 | Connection closed | Соединение закрыто (часто из-за stdout) |
-32001 | Request timeout | Таймаут запроса |
-32002 | Resource not found | Ресурс не найден |
-32003 | Tool not found | Инструмент не найден |
-32004 | Prompt not found | Промпт не найден |
Симптомы: Сервер запускается, но сразу отключается. В логах: “Connection closed unexpectedly”.
Причина: Вывод в stdout нарушает JSON-RPC протокол.
import sysimport logging
# ❌ НЕПРАВИЛЬНОprint("Debug message") # Ломает JSON-RPC!
# ✅ ПРАВИЛЬНОlogging.basicConfig(stream=sys.stderr, level=logging.DEBUG)logger = logging.getLogger(__name__)logger.debug("Debug message")
# Или напрямуюprint("Debug message", file=sys.stderr)// ❌ НЕПРАВИЛЬНОconsole.log("Debug message"); // Идёт в stdout!
// ✅ ПРАВИЛЬНОconsole.error("Debug message"); // Идёт в stderr
// Или создайте helperfunction log(msg: string) { process.stderr.write(`[DEBUG] ${msg}\n`);}import ( "log" "os")
// ❌ НЕПРАВИЛЬНОfmt.Println("Debug message")
// ✅ ПРАВИЛЬНОlog.SetOutput(os.Stderr)log.Println("Debug message")Симптомы: {"error": {"code": -32002, "message": "Resource not found: xxx"}}
Причина: Клиент запрашивает ресурс, который не зарегистрирован на сервере.
@mcp.resource("config://settings") # Точный URIdef get_settings(): return {"theme": "dark"}# ❌ Зарегистрировано@mcp.resource("config://settings")
# ❌ Запрашивается (не совпадает)# "config://setting" — нет 's' в конце# "config:/settings" — одна косая черта# "settings" — нет схемы
# ✅ Правильный запрос# "config://settings"Симптомы: {"error": {"code": -32003, "message": "Tool not found: xxx"}}
@mcp.tool() # Декоратор обязателенdef my_tool(param: str) -> str: """Описание инструмента""" return f"Result: {param}"# Имя берётся из имени функции@mcp.tool()def calculate_sum(a: int, b: int) -> int: # Имя: "calculate_sum" return a + b
# Или можно задать явно@mcp.tool(name="sum") # Имя: "sum"def calculate_sum(a: int, b: int) -> int: return a + bСимптомы: Сервер запускается, но инструменты не появляются в списке.
Проверьте конфигурацию
# macOScat ~/Library/Application\ Support/Claude/claude_desktop_config.jsonJSON должен быть валидным (проверьте запятые и кавычки).
Проверьте пути Используйте абсолютные пути:
{ "mcpServers": { "my-server": { "command": "/usr/bin/python3", "args": ["/Users/me/project/server.py"] } }}Проверьте запуск вручную
python /Users/me/project/server.pyЕсли есть ошибки — исправьте их.
Проверьте логи Claude
# macOStail -f ~/Library/Logs/Claude/mcp*.logПолностью перезапустите Claude
// ❌ Неправильно: относительный путь{ "mcpServers": { "my-server": { "command": "python", "args": ["server.py"] } }}
// ✅ Правильно: абсолютный путь{ "mcpServers": { "my-server": { "command": "/usr/bin/python3", "args": ["/Users/me/project/server.py"] } }}// ❌ Неправильно: лишняя запятая{ "mcpServers": { "my-server": { "command": "python", "args": ["server.py"], // <-- Лишняя запятая! } }}
// ✅ Правильно{ "mcpServers": { "my-server": { "command": "python", "args": ["server.py"] } }}Error: connection refusedError: password authentication failedError: database "xxx" does not existРешения:
import osfrom mcp.server.fastmcp import FastMCP
mcp = FastMCP("db-server")
# 1. Проверьте DATABASE_URLDATABASE_URL = os.getenv("DATABASE_URL")if not DATABASE_URL: raise ValueError("DATABASE_URL не установлена")
# 2. Проверьте формат URL# postgresql://user:password@host:port/database# postgresql://postgres:secret@localhost:5432/mydb
# 3. Используйте connection poolimport asyncpg
pool = None
@mcp.tool()async def query_db(sql: str) -> str: global pool if pool is None: pool = await asyncpg.create_pool(DATABASE_URL)
async with pool.acquire() as conn: result = await conn.fetch(sql) return str(result)Error: unable to open database fileError: database is lockedРешения:
import sqlite3import os
# 1. Проверьте путь к файлуdb_path = "/path/to/database.db"if not os.path.exists(db_path): raise FileNotFoundError(f"БД не найдена: {db_path}")
# 2. Используйте правильные флагиconn = sqlite3.connect( db_path, check_same_thread=False, # Для многопоточности timeout=30.0 # Таймаут блокировки)
# 3. Для read-only доступаconn = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)Симптомы: ModuleNotFoundError: No module named 'mcp'
{ "mcpServers": { "my-server": { "command": "/path/to/venv/bin/python", "args": ["/path/to/server.py"] } }}Или используйте uvx:
{ "mcpServers": { "my-server": { "command": "uvx", "args": ["--from", "mcp", "mcp", "run", "server.py"] } }}# Скомпилируйте TypeScriptnpx tsc
# Или используйте ts-nodenpm install -D ts-node typescript @types/node{ "mcpServers": { "my-server": { "command": "npx", "args": ["ts-node", "/path/to/server.ts"] } }}{ "compilerOptions": { "module": "ESNext", "moduleResolution": "Node", "target": "ES2022" }}{ "type": "module"}Request timeout ошибки@mcp.tool()async def long_operation(data: str) -> str: """Долгая операция""" # Уведомляем о прогрессе await mcp.request_context.session.send_progress( progress=0, total=100, message="Начинаю обработку..." )
# Делаем работу result = await process_data(data)
await mcp.request_context.session.send_progress( progress=100, total=100, message="Готово!" )
return resultimport asyncioimport aiohttp
@mcp.tool()async def fetch_data(url: str) -> str: """Получить данные из URL""" async with aiohttp.ClientSession() as session: async with session.get(url, timeout=30) as response: return await response.text()@mcp.tool()def get_file(path: str) -> str: """Читает файл (макс 100KB)""" MAX_SIZE = 100 * 1024
with open(path, 'r') as f: content = f.read(MAX_SIZE)
if len(content) == MAX_SIZE: content += "\n... (файл обрезан)"
return contentnpx @modelcontextprotocol/inspector python server.py# Проверка initializeecho '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | python server.py
# Список toolsecho '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | python server.py# Pythonpip show mcp
# Node.jsnpm list @modelcontextprotocol/sdk# Pythonpip install --upgrade mcp
# Node.jsnpm update @modelcontextprotocol/sdkДа, добавьте несколько записей в mcpServers:
{ "mcpServers": { "server1": { "command": "python", "args": ["server1.py"] }, "server2": { "command": "python", "args": ["server2.py"] } }}Используйте переменные окружения:
{ "mcpServers": { "my-server": { "command": "python", "args": ["server.py"], "env": { "API_KEY": "xxx", "DATABASE_URL": "postgresql://..." } } }}| Клиент | Логи |
|---|---|
| Claude Desktop (macOS) | ~/Library/Logs/Claude/mcp*.log |
| Claude Desktop (Windows) | %APPDATA%\Claude\logs\ |
| VS Code | View → Output → MCP |
| Cursor | Developer Tools → Console |
MCP Inspector
Инструменты разработчика — подробнее о Inspector
Production Checklist
Чеклист — подготовка к production
Примеры кода
25+ примеров — работающий код
Настройка клиентов
Клиенты — Claude, VS Code, Cursor