Перейти до змісту

Запуск сервера

Машинний переклад

Цю сторінку перекладено автоматично з англомовної документації, і основною версією є англомовна сторінка. Якщо щось читається неправильно, на сторінці Переклади пояснено, як про це повідомити.

mcp.run() запускає сервер.

Єдине рішення, яке доводиться ухвалити, — це транспорт: як саме рухаються байти між сервером і його клієнтом.

Вибір транспорту

Транспорт Що це Коли
stdio Хост запускає ваш файл як підпроцес і спілкується через його stdin та stdout. Локальні сервери. Значення за замовчуванням.
streamable-http Справжній HTTP-сервер, що слухає порт. Усе, що ви розгортаєте.
sse Старіший HTTP-транспорт. Ніколи.

Warning

У ревізії протоколу 2025-03-26 SSE поступився місцем Streamable HTTP. mcp.run(transport="sse") досі працює, зі своїми параметрами sse_path= і message_path=, але існує лише для клієнтів, які ще не перейшли. Не будуйте на ньому нічого нового.

mcp.run()

server.py
from mcp.server import MCPServer

mcp = MCPServer("Bookshop")


@mcp.tool()
def search_books(query: str) -> str:
    """Search the catalog by title or author."""
    return f"Found 3 books matching {query!r}."


if __name__ == "__main__":
    mcp.run()
  • run() синхронний. Він блокує виконання на весь час життя сервера.
  • Без аргументу транспорт — stdio.
  • Він стоїть під if __name__ == "__main__":, бо все, що завантажує сервер (mcp dev, mcp run, mcp install, ваші тести), імпортує цей файл. Ця умова не дає імпорту перетворитися на запущений сервер.

stdio

Налаштовувати нічого. Хост запускає ваш файл як дочірній процес, пише запити в його stdin і читає відповіді з його stdout.

Запустіть його самі — і побачите наслідок:

python server.py

Нічого не виводиться, і керування не повертається. Сервер чекає на stdin, поки хост заговорить першим.

Це також означає, що stdout і є каналом передачі даних. Під час обслуговування SDK переносить цей канал на приватний дескриптор, а вивід, що скидається (flush) у stdout (підпроцес, який пише в успадкований stdout, print() зі скиданням буфера), перенаправляє в stderr, де він не може зіпсувати потік. Вивід, скинутий у stdout до початку обслуговування (скрипт-обгортка з echo, небуферизований print під час імпорту), усе одно потрапляє в канал — як і print(), що лишається в буфері, доки інтерпретатор не спорожнить його під час завершення. Для виводу, який справді потрібен, правильний інструмент — модуль logging: його обробник скидає кожен запис у stderr одразу, щойно той з'являється. Докладніше — на сторінці Логування.

Спробуйте самі

uv run mcp dev server.py

Inspector робить рівно те саме, що й справжній хост: запускає server.py як підпроцес і під'єднується до нього через stdio.

Порт ви йому не вказували. Його й немає.

Streamable HTTP

Щоб натомість виставити той самий сервер на порт, вкажіть транспорт (і його параметри) в run():

server.py
from mcp.server import MCPServer

mcp = MCPServer("Bookshop")


@mcp.tool()
def search_books(query: str) -> str:
    """Search the catalog by title or author."""
    return f"Found 3 books matching {query!r}."


if __name__ == "__main__":
    mcp.run(transport="streamable-http", port=3001)

Цей один рядок будує застосунок Starlette і обслуговує його через uvicorn. Клієнти під'єднуються до http://127.0.0.1:3001/mcp.

Кожен транспорт має власні іменовані аргументи, усі — в run():

  • host / port: де слухати. За замовчуванням 127.0.0.1 і 8000.
  • streamable_http_path: де розташована кінцева точка MCP. За замовчуванням /mcp.
  • json_response=True: відповідати на кожен POST одним JSON-тілом замість SSE-потоку. У такому тілі є місце для відповіді й ні для чого іншого, тож інструмент, який посеред запиту звертається назад до клієнта (ctx.elicit(), семплювання (sampling)), на цьому відрізку викидає NoBackChannelError, а сповіщення, прив'язані до поточного виклику (перебіг виконання від ctx.report_progress(), повідомлення журналу окремого виклику), відкидаються; окремий потік GET і далі несе не пов'язані з ним.
  • stateless_http=True: новий транспорт на кожен запит, без відстеження сесій.
  • max_request_body_size: найбільший прийнятний розмір тіла POST у байтах. За замовчуванням 4 МіБ; більші запити отримують HTTP 413 ще до розбору чи створення сесії. Збільшуйте його лише тоді, коли легітимні MCP-повідомлення перевищують цей розмір.
  • event_store, retry_interval, transport_security: відновлюваність і захист від DNS-rebinding. Вони можуть зачекати, доки ви не розгорнете сервер деінде, крім localhost; transport_security описано на сторінці Розгортання та масштабування.

Warning

Параметри транспорту передаються в run(), а не в MCPServer(...). Конструктор описує, чим ваш сервер є: ім'я, версія, інструкції. run() описує, як його обслуговувати. Переплутайте — і Python відповість ще до того, як у справу взагалі втрутиться MCP:

TypeError: MCPServer.__init__() got an unexpected keyword argument 'port'

run() — це короткий шлях. Щойно знадобиться більше (сервер, змонтований у наявний застосунок, два сервери в одному процесі, CORS для браузерних клієнтів), ви будуєте ASGI-застосунок самі й віддаєте його будь-якому ASGI-хосту. Про це — Додавання до наявного застосунку.

Налаштування сервера

Кілька речей, що стосуються запуску, до транспорту не належать. Це аргументи конструктора:

server.py
from mcp.server import MCPServer

mcp = MCPServer("Bookshop", log_level="DEBUG")


@mcp.tool()
def search_books(query: str) -> str:
    """Search the catalog by title or author."""
    return f"Found 3 books matching {query!r}."


if __name__ == "__main__":
    mcp.run()
  • log_level: передається в logging.basicConfig() тієї ж миті, коли створюється MCPServer(...). Це налаштовує кореневий логер, тож задає рівень і для ваших власних логерів, а не лише для логерів SDK. За замовчуванням "INFO".
  • debug: передається далі в застосунок Starlette, який будують HTTP-транспорти. За замовчуванням False.

Обидва потрапляють у mcp.settings, звідки їх можна прочитати під час виконання.

Команда mcp

Необов'язковий набір залежностей [cli] встановлює невеличкий інструмент командного рядка поверх усього цього.

mcp dev запускає сервер під MCP Inspector:

uv run mcp dev server.py
uv run mcp dev server.py --with pandas --with numpy
uv run mcp dev server.py --with-editable .

--with додає пакети до середовища, яке вона будує; --with-editable встановлює в нього ваш власний пакет. Потрібен npx у PATH: Inspector — це застосунок на Node.js.

mcp run імпортує файл, знаходить об'єкт сервера (mcp, server або app на рівні модуля) і викликає на ньому run():

uv run mcp run server.py
uv run mcp run server.py:bookshop

Суфікс після : називає об'єкт, якщо його ім'я не mcp, server чи app.

Блок if __name__ == "__main__": тут ніколи не виконується: mcp run викликає run() сама, і єдиний параметр, який вона передає далі, — --transport.

mcp install реєструє сервер у Claude Desktop, щоб застосунок запускав його за вас:

uv run mcp install server.py --name "Bookshop"
uv run mcp install server.py -v API_KEY=abc123 -f .env

-v KEY=VALUE і -f .env записують змінні середовища в цей запис. Claude Desktop запускає ваш сервер у власному процесі. Середовища вашої оболонки там немає.

Claude Desktop — єдиний хост, який знає mcp install. Кожен інший хост (Claude Code, Cursor, VS Code) приймає ту саму команду запуску у власному файлі конфігурації; кожен із них описано на сторінці Під'єднання до справжнього хоста.

mcp version виводить версію встановленого SDK.

Tip

mcp dev і mcp run розуміють лише MCPServer. Якщо ви будуєте на низькорівневому Server, запускати його доведеться самостійно. Див. Низькорівневий Server.

Підсумки

  • Транспорт — це спосіб, у який байти дістаються сервера: stdio для локального підпроцесу, streamable-http для порту. SSE замінено.
  • mcp.run() обирає транспорт. Без аргументу це stdio, і виклик блокує виконання.
  • Кожен параметр транспорту (host, port, streamable_http_path, ...) — це аргумент run() і ніколи не MCPServer(...).
  • Тримайте run() під if __name__ == "__main__":. Усе, що завантажує сервер, спершу імпортує файл.
  • log_level= і debug= — аргументи конструктора; вони потрапляють у mcp.settings.
  • mcp dev для Inspector, mcp run щоб виконати файл, mcp install для Claude Desktop, mcp version для версії.
  • Транспорт ніколи не змінює того, чим ваш сервер є: усі три файли на цій сторінці надають ідентичний інструмент.

Коли обмеженням стає сам run() (сервер усередині застосунку, що вже існує), — це Додавання до наявного застосунку. Справжнє ім'я хоста й більше ніж один робочий процес — це Розгортання та масштабування. А якщо частина ваших клієнтів досі на версії специфікації 2025-11-25 чи ранішій, добра новина — на сторінці Обслуговування клієнтів старого покоління.