MCP Inspector
GitHub репозиторий — исходный код и документация
MCP Inspector, CLI и инструменты отладки для разработки MCP серверов
MCP Inspector — официальный веб-интерфейс для тестирования и отладки MCP серверов. Позволяет интерактивно вызывать tools, читать resources и тестировать prompts.
npx @modelcontextprotocol/inspector <команда_запуска_сервера>npx @modelcontextprotocol/inspector python server.pynpx @modelcontextprotocol/inspector npm run startnpx @modelcontextprotocol/inspector go run main.gonpx @modelcontextprotocol/inspector docker run -i my-mcp-serverПосле запуска откройте http://localhost:6274 в браузере.
| Порт | Назначение |
|---|---|
6274 | Веб-интерфейс Inspector |
6277 | Внутренний proxy для MCP |
Inspector можно использовать без веб-интерфейса:
# Только проверка подключенияnpx @modelcontextprotocol/inspector --cli python server.py
# Вызов конкретного toolecho '{"method":"tools/call","params":{"name":"add","arguments":{"a":5,"b":3}}}' | \ npx @modelcontextprotocol/inspector --cli python server.pyПакет mcp включает CLI для разработки:
pip install mcp# Запуск сервераmcp run server.py
# Запуск с отладкойmcp run server.py --debug
# Информация о сервереmcp info server.pymcp infoServer: my-first-serverVersion: 1.0.0
Tools (2): - add: Сложить два числа - greet: Поприветствовать по имени
Resources (1): - info://about
Prompts (0): (none)import sysimport logging
# Настройка логгера на stderrlogging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', stream=sys.stderr # Важно!)
logger = logging.getLogger(__name__)
@mcp.tool()def my_tool(param: str) -> str: logger.debug(f"Вызван my_tool с param={param}") return f"Результат: {param}"// Логирование в stderrfunction log(message: string) { process.stderr.write(`[DEBUG] ${new Date().toISOString()} ${message}\n`);}
// Использованиеserver.setRequestHandler(CallToolRequestSchema, async (request) => { log(`Tool called: ${request.params.name}`); // ...});import ( "log" "os")
func init() { // Логи в stderr log.SetOutput(os.Stderr)}
func main() { log.Println("Server starting...") // ...}import logging
# Для разработкиlogging.basicConfig(level=logging.DEBUG, stream=sys.stderr)
# Для productionlogging.basicConfig(level=logging.WARNING, stream=sys.stderr)| Уровень | Когда использовать |
|---|---|
DEBUG | Детальная информация для отладки |
INFO | Подтверждение нормальной работы |
WARNING | Потенциальные проблемы |
ERROR | Ошибки, сервер продолжает работать |
CRITICAL | Критические ошибки, сервер остановится |
import pytestfrom mcp.server.fastmcp import FastMCP
# Создаём тестовый серверmcp = FastMCP("test-server")
@mcp.tool()def add(a: int, b: int) -> int: """Сложить два числа""" return a + b
@mcp.tool()def divide(a: float, b: float) -> float: """Разделить a на b""" if b == 0: raise ValueError("Деление на ноль") return a / b
# Тестыclass TestTools: def test_add(self): result = add(5, 3) assert result == 8
def test_add_negative(self): result = add(-5, 3) assert result == -2
def test_divide(self): result = divide(10, 2) assert result == 5.0
def test_divide_by_zero(self): with pytest.raises(ValueError, match="Деление на ноль"): divide(10, 0)import { describe, it, expect, beforeAll, afterAll } from 'vitest';import { spawn, ChildProcess } from 'child_process';
describe('MCP Server Integration', () => { let serverProcess: ChildProcess;
beforeAll(async () => { serverProcess = spawn('npm', ['run', 'start'], { stdio: ['pipe', 'pipe', 'pipe'] }); // Ждём запуска await new Promise(resolve => setTimeout(resolve, 1000)); });
afterAll(() => { serverProcess.kill(); });
it('should respond to initialize', async () => { const request = JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'test', version: '1.0.0' } } });
serverProcess.stdin!.write(request + '\n');
const response = await new Promise<string>(resolve => { serverProcess.stdout!.once('data', data => resolve(data.toString())); });
const parsed = JSON.parse(response); expect(parsed.result).toBeDefined(); expect(parsed.result.serverInfo).toBeDefined(); });});# Pythonpytest tests/ -v
# TypeScriptnpm test
# С coveragepytest tests/ --cov=src --cov-report=htmlnpm test -- --coverage# Запустите серверpython server.py
# В другом терминале отправьте запросecho '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | python server.py// Запрос: initialize{"jsonrpc":"2.0","id":1,"method":"initialize","params":{ "protocolVersion":"2024-11-05", "capabilities":{}, "clientInfo":{"name":"test","version":"1.0"}}}
// Ответ{"jsonrpc":"2.0","id":1,"result":{ "protocolVersion":"2024-11-05", "serverInfo":{"name":"my-server","version":"1.0.0"}, "capabilities":{"tools":{}}}}
// Запрос: tools/list{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
// Ответ{"jsonrpc":"2.0","id":2,"result":{"tools":[ {"name":"add","description":"Сложить два числа","inputSchema":{...}}]}}
// Запрос: tools/call{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{ "name":"add", "arguments":{"a":5,"b":3}}}
// Ответ{"jsonrpc":"2.0","id":3,"result":{ "content":[{"type":"text","text":"8"}]}}#!/usr/bin/env python3"""health_check.py - Проверка работоспособности MCP сервера"""
import subprocessimport jsonimport sys
def check_server(command: list[str]) -> bool: """Проверяет, что сервер отвечает на initialize"""
init_request = json.dumps({ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": {"name": "health-check", "version": "1.0"} } }) + "\n"
try: result = subprocess.run( command, input=init_request, capture_output=True, text=True, timeout=5 )
response = json.loads(result.stdout.strip())
if "result" in response and "serverInfo" in response["result"]: print(f"✅ Server OK: {response['result']['serverInfo']}") return True else: print(f"❌ Invalid response: {response}") return False
except subprocess.TimeoutExpired: print("❌ Server timeout") return False except json.JSONDecodeError as e: print(f"❌ Invalid JSON: {e}") return False except Exception as e: print(f"❌ Error: {e}") return False
if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: python health_check.py <command>") print("Example: python health_check.py python server.py") sys.exit(1)
command = sys.argv[1:] success = check_server(command) sys.exit(0 if success else 1)# Проверка Python сервераpython health_check.py python server.py
# Проверка Docker контейнераpython health_check.py docker run -i my-mcp-server
# В CI/CDpython health_check.py python server.py && echo "Deploy OK"version: '3.8'
services: mcp-server: build: context: . dockerfile: Dockerfile.dev volumes: - .:/app - /app/node_modules # Для Node.js environment: - DEBUG=1 - LOG_LEVEL=debug stdin_open: true tty: true
inspector: image: node:20 command: npx @modelcontextprotocol/inspector nc mcp-server 3000 ports: - "6274:6274" depends_on: - mcp-serverFROM python:3.11-slim
WORKDIR /app
# Установка зависимостей для hot-reloadRUN pip install watchdog
COPY requirements.txt .RUN pip install -r requirements.txt
# Копируем кодCOPY . .
# Hot-reload с watchmedoCMD ["watchmedo", "auto-restart", "--patterns=*.py", "--recursive", "--", "python", "server.py"]MCP Inspector
GitHub репозиторий — исходный код и документация
Python SDK
mcp на PyPI — включает CLI инструменты
Troubleshooting
Решение проблем — типичные ошибки и их решения
Production Checklist
Чеклист — подготовка к production