Skip to main content
Glama

Создайте свой собственный MCP-сервер (и разверните его)

Полноценный, работающий MCP-сервер, который превращает LLM API в MCP-инструменты — создан для обучения. Он работает локально через stdio для Claude Desktop / Claude Code, и удаленно через HTTP после развертывания.

Работает на Groq — быстрый вывод, совместимый с OpenAI API, бесплатный тариф, который выдерживает нагрузку от целой аудитории студентов во время воркшопа.

Всё находится в одном файле: server.py. ~170 строк, включая комментарии.


Часть 0 — Что такое MCP за одну минуту

MCP (Model Context Protocol) — это стандартный способ дать AI-клиенту новые возможности. Вы пишете сервер; любой MCP-клиент может его использовать.

Сервер может предоставлять три типа объектов:

Примитив

Что это такое

Кто управляет

Инструмент

Функция, которую может вызвать модель

Модель решает

Ресурс

Данные только для чтения, которые клиент может подтянуть

Клиент/приложение решает

Подсказка

Шаблон подсказки для повторного использования

Пользователь выбирает

Два транспорта:

  • stdio — клиент запускает ваш сервер как подпроцесс и общается через stdin/stdout. Только локально. Никаких сетей. Так работают 90% MCP-серверов.

  • streamable HTTP — ваш сервер — это веб-сервис по URL. Это то, что вы развертываете, чтобы другие люди (или хостированные клиенты) могли его использовать.

Один и тот же server.py делает и то, и другое. В этом весь фокус.


Related MCP server: mcp-cli-catalog

Часть 1 — Что мы создаем

llm-toolkit: MCP-сервер, который предоставляет любому MCP-клиенту четыре инструмента на основе LLM.

Инструмент

Делает

ask_llm

Задать вопрос, выбрать краткий / подробный / eli5

summarize

Текст → N маркерованных пунктов

translate

Перевести, сохраняя markdown и блоки кода

extract_json

Неструктурированный текст → структурированный JSON

Плюс один ресурс (config://server-info) и одна подсказка (code_review), чтобы студенты увидели все три примитива.


Часть 2 — Запустите его локально

Настройка

python -m venv .venv

Windows: .\\.venv\Scripts\activate — macOS/Linux: source .venv/bin/activate

pip install -r requirements.txt

Получите бесплатный ключ на console.groq.com → API Keys. Затем скопируйте .env.example в .env и вставьте его:

cp .env.example .env

.env находится в .gitignore. Сервер загружает его автоматически из своей собственной директории, поэтому он работает независимо от того, откуда клиент его запускает.

Проверьте его перед подключением

MCP Inspector — лучший инструмент для обучения: он показывает список инструментов и позволяет вызывать их вручную, без AI-клиента.

npx @modelcontextprotocol/inspector python server.py

Откройте напечатанный URL, нажмите Connect, затем List Tools. Вы увидите все четыре.


Часть 3 — Подключите его к клиенту

Claude Code

claude mcp add llm-toolkit -e GROQ_API_KEY=gsk_... -- python /absolute/path/to/server.py

Или закоммитьте .mcp.json в корне вашего проекта, чтобы вся команда получила его — см. .mcp.json.example.

Claude Desktop

Отредактируйте claude_desktop_config.json:

  • macOS — ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows — %APPDATA%\Claude\claude_desktop_config.json

Вставьте блок mcpServers из .mcp.json.example, затем полностью закройте и откройте заново Claude Desktop. Инструменты появятся под иконкой инструментов.

Только абсолютные пути. Причина №1, по которой локальный MCP-сервер "не появляется" — это относительный путь — рабочая директория клиента не совпадает с вашей. Используйте полный путь как к бинарнику python (.venv/bin/python), так и к server.py.


Часть 4 — Разверните его

Переключитесь в режим HTTP одним флагом:

python server.py --http

Сервер теперь доступен по адресу http://localhost:8000/mcp. Отправьте ту же команду в контейнер.

Вариант A — Render, без Docker (рекомендуется)

У Render есть родной Python runtime. Никакого Dockerfile, никакой сборки контейнера. Он устанавливает requirements.txt и запускает вашу стартовую команду напрямую. Это самый быстрый путь от ноутбука до публичного URL.

Шаг 1 — получите код на GitHub.

git init && git add -A && git commit -m "MCP server"

Создайте пустой репозиторий на github.com/new, затем:

git remote add origin https://github.com/<you>/llm-toolkit-mcp.git && git push -u origin main

Шаг 2 — создайте сервис.

Панель управления Render → New → Web Service → подключите репозиторий. Render читает render.yaml и настраивается автоматически:

Настройка

Значение

Runtime

Python (не Docker)

Build command

pip install -r requirements.txt

Start command

python server.py --http

Шаг 3 — установите ключ. Панель управления → Environment → добавьте GROQ_API_KEY. Он помечен sync: false в render.yaml, поэтому хранится только в панели управления, никогда в git.

Шаг 4 — разверните. Ваша публичная конечная точка — https://<your-app>.onrender.com/mcp.

Отсутствие проверки здоровья намеренно. GET /mcp открывает SSE-поток, который остается открытым по задумке. Проверка здоровья, направленная на него, зависает, и Render расценивает таймаут как мертвый сервис и перезапускает его в цикле. С пропущенным healthCheckPath Render просто проверяет, что процесс привязывается к $PORT — правильная проверка для этого сервера.

Экземпляры бесплатного тарифа засыпают после ~15 мин бездействия. Первый вызов после сна занимает ~30–50 секунд, пока он просыпается. Некоторые MCP-клиенты выходят из таймаута до этого и сообщают о сервере как о неработающем. Прогрейте его с помощью curl до начала занятия.

Вариант B — Другие хосты без Docker

Хост

Как

Railway

Подключите репозиторий. Nixpacks автоматически обнаруживает Python. Установите start command на python server.py --http.

Hugging Face Spaces

Бесплатно, без сна. Docker Space, или Gradio Space с кастомной заглушкой app.py.

Google Cloud Run

gcloud run deploy --source . — собирает из исходного кода, Dockerfile не нужен.

Любой VPS

pip install -r requirements.txt, затем запустите под systemd или tmux.

Вариант C — Fly.io

fly launch --no-deploy
fly secrets set GROQ_API_KEY=gsk_...
fly deploy

Конечная точка: https://<your-app>.fly.dev/mcp

Вариант D — Любой хост для контейнеров

Dockerfile сохранен для хостов, которым нужен контейнер. Работает на Railway, Cloud Run, ECS, VPS:

docker build -t llm-toolkit-mcp .
docker run -p 8000:8000 -e GROQ_API_KEY=gsk_... llm-toolkit-mcp

Проверьте развертывание

Одна команда curl доказывает, что сервер жив и говорит на MCP:

curl -X POST https://your-app.onrender.com/mcp -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'

Вы должны получить блок serverInfo с именем llm-toolkit.

Подключите клиент к развернутому серверу

claude mcp add --transport http llm-toolkit https://your-app.onrender.com/mcp

Студенты вставляют эту одну строку и мгновенно получают ваши четыре инструмента. Это момент окупаемости всего воркшопа — никакой установки, никакого ключа, никакого Python на их машине.

Публичный доступ — прочитайте это сначала

Развернутый MCP-сервер без аутентификации открыт для всего интернета. Любой, кто узнает URL, может вызывать ваши инструменты, и каждый вызов тратит вашу квоту Groq.

Для воркшопа это обычно нормально, и именно бесплатный тариф Groq делает это нормальным: когда квота заканчивается, вы получаете ошибки HTTP 429, а не счет. Режим отказа — "инструменты перестают отвечать", а не "неожиданный счет".

Это перестает быть нормальным, как только вы помещаете за ним платный ключ. Тогда добавьте аутентификацию перед тем, как делиться URL — параметр auth MCP SDK или API-шлюз перед ним.

Две привычки, которые стоит сохранить в любом случае:

  • Относитесь к URL как к полусекретному. Делитесь им в классе, не публикуйте его открыто.

  • Ротируйте ключ после воркшопа. Это один клик в панели управления.

Часть 5 — Что стоит преподавать явно

Докстринг — это API. Модель выбирает инструменты, читая докстринг и подсказки типов. Расплывчатый докстринг означает инструмент, который никогда не будет вызван. Это самый важный момент во всем файле.

Одна функция владеет провайдером. Каждый инструмент вызывает call_llm(). Замена Groq на OpenAI, Anthropic или локальный Ollama означает редактирование этой одной функции — четыре инструмента никогда не меняются. Продемонстрируйте это вживую; это производит сильное впечатление.

Возвращайте ошибки как строки, не вызывайте исключения. call_llm перехватывает GroqError и возвращает сообщение как текст. Клиент показывает пользователю реальную ошибку вместо мертвого вызова инструмента.

stateless_http=True означает отсутствие липких сессий, поэтому сервер масштабируется за балансировщиком нагрузки. Выключайте это только если добавляете состояние для каждой сессии.

Никогда не коммитьте ключ. .env находится в .gitignore, render.yaml использует sync: false, Fly использует fly secrets.

Публичные HTTP-серверы открыты по умолчанию. Этот не имеет аутентификации — нормально для демо, не для продакшена. Реальные развертывания добавляют OAuth через параметр auth SDK или находятся за API-шлюзом.

Дрейф версий реален. MCP Python SDK 2.0 переименовал FastMCP в MCPServer. Большинство руководств в интернете все еще показывают FastMCP и не будут работать на свежей установке. Хороший момент, чтобы научить читать установленный пакет вместо того, чтобы доверять посту в блоге.


Часть 6 — Упражнения для класса

  1. Добавьте инструмент sentiment(text). (Скопируйте summarize, измените системный промпт.)

  2. Сделайте так, чтобы ask_llm принимал аргумент max_tokens и наблюдайте, как схема обновляется автоматически в Inspector.

  3. Направьте call_llm на другого провайдера, не трогая ни один инструмент.

  4. Добавьте ресурс config://usage, который сообщает, сколько вызовов инструментов обслужил процесс. (Подсказка: счетчик на уровне модуля.)

  5. Намеренно сломайте докстринг, затем попросите модель использовать этот инструмент. Наблюдайте, как она не может выбрать инструмент. В этом урок.


Часть 7 — Как заставить других его использовать

Предоставление инструментов другому человеку — это три отдельные проблемы: доступность, подключаемость, обнаруживаемость. Решайте их в таком порядке.

1. Доступность. Сервер на localhost может использовать только один человек. Разверните его (Часть 4), и у вас будет публичный URL. Ниже ничего не работает, пока это не сделано.

2. Подключаемость. Дайте людям USING-IT.md — отдельную страницу с конфигурацией копипаста для Claude Code, Claude Desktop и Cursor, плюс таблицу устранения неполадок. Для воркшопа удаленный маршрут — тот, который нужно использовать: студенты вставляют одну строку и имеют работающие инструменты без Python, без репозитория и без собственного API-ключа.

3. Обнаруживаемость. Только если вы хотите, чтобы незнакомцы нашли его, а не только ваш класс:

Канал

Что это дает

GitHub темы mcp, mcp-server, model-context-protocol

Бесплатный поисковый трафик

Официальный реестр MCP

Отображение в UI клиентов "обзор серверов"

Списки сообществ awesome-mcp-servers

PR для добавления вашего репозитория

Smithery / Glama и подобные каталоги

Кнопки хостированной установки

Требования реестра быстро меняются — проверьте текущую документацию реестра MCP на предмет формата манифеста перед публикацией.

Замечание о честном потолке. Люди принимают MCP-сервер, когда он делает то, что они не могут сделать сами. Этот оборачивает обычную LLM, которая уже встроена в большинство клиентов — идеально для обучения протоколу, слабо как продукт. Сервер, который получает доступ к вашей базе данных, вашему внутреннему API или вашим проприетарным данным — это тот, который получает реальных пользователей. Стоит сказать это вслух классу.


Часть 8 — Что делает его готовым к продакшену

Версия для воркшопа и продакшен-версия отличаются способами, которые не имеют ничего общего с MCP. Это список, и каждый пункт существует из-за сбоя, который произошел при создании этого сервера.

Защита ключа

Публичная MCP-конечная точка — это публичная конечная точка для расходов: каждый вызов стоит вас.**

(Примечание: текст обрывается. Оригинальный документ, вероятно, продолжается. Если вы хотите, я могу продолжить перевод, начиная с подраздела "Защита ключа" и далее.)

Защита

Переменная окружения

По умолчанию

Зачем

Bearer-аутентификация

MCP_AUTH_TOKEN

пусто = открыто

Ограничить доступ после того, как за ним стоит платный ключ

Лимит запросов

RATE_LIMIT_PER_MIN

30/IP

Один скрипт не может исчерпать вашу квоту

Ограничение ввода

MAX_INPUT_CHARS

20000

Вставленный роман отклоняется до того, как он потратит токены

Ограничение тела

MAX_BODY_BYTES

1 МБ

Слишком большие полезные нагрузки отклоняются до парсинга

Аутентификация по умолчанию выключена, чтобы сервер оставался открытым для воркшопа на бесплатном ключе. Включите её, прежде чем направлять платный ключ на публичный URL:

MCP_AUTH_TOKEN=$(python -c "import secrets;print(secrets.token_urlsafe(32))") python server.py --http

Затем клиенты отправляют Authorization: Bearer <token>.

Выживание с провайдером

Модели снимаются с поддержки без уведомления. Groq удалил llama-3.3-70b-versatile во время разработки — она работала в 07:15, а через час выдавала 404. Все инструменты сломались одновременно, и 404 выглядит как «ваш сервер сломан», а не «вендор перенёс модель».

MODEL_CHAIN решает это: при ошибке «модель не найдена» вызов переходит к следующей модели вместо того, чтобы завершиться ошибкой. Другие ошибки — неверный ключ, лимит запросов — завершаются быстро, потому что повторять их через пять моделей — пустая трата времени.

Тайм-ауты (LLM_TIMEOUT_SECONDS) и повторные попытки (LLM_MAX_RETRIES) передаются SDK вендора, которые уже правильно реализуют экспоненциальную задержку.

Проверки работоспособности

/health возвращает простой JSON. Никогда не проверяйте /mcp — это SSE-поток, который по замыслу остаётся открытым, поэтому проверка зависает, платформа считает сервер мёртвым, и вы получаете цикл перезапуска, который выглядит как сбой. Это стоило реального цикла отладки здесь.

Логирование

Всё идёт в stderr, никогда в stdout. В режиме stdio stdout несёт JSON-RPC-поток, поэтому один случайный print() нарушает протокол. Это самый распространённый способ сломать MCP-сервер при отладке.

Промежуточное ПО уровня MCP логирует каждый метод с его длительностью и работает для обоих транспортов.

Тесты и CI

pytest tests/ работает офлайн без API-ключа и ничего не тратит. Он покрывает истечение окна лимита запросов, ограничения ввода, запасную модель, сохранение схемы инструментов и проверку конфигурации.

GitHub Actions запускает набор на 3.11 и 3.12, загружает сервер и сканирует всю историю git на наличие закоммиченных API-ключей — ошибка, которая невосстановима, потому что отправленный ключ становится публичным в момент его появления.

Известные ограничения

Стоит честно рассказать классу о том, чего пока не хватает:

  • Лимит запросов — на процесс. Масштабируйте до N экземпляров, и вы получите N-кратный лимит. Замените на Redis до того, как это станет проблемой.

  • Один общий токен, а не ключи на пользователя. Хорошо для класса, но не для клиентов.

  • Нет учёта использования. Вы не можете сказать, кто что потратил.

  • Холодный старт на бесплатном тарифе всё ещё занимает 30–50 секунд после простоя.


Карта файлов

Файл

Зачем он существует

server.py

Весь сервер — инструменты, ресурс, промпт

requirements.txt

mcp[cli] + groq + python-dotenv

Dockerfile

Контейнер для любого хоста

render.yaml

Развёртывание в один клик на Render

fly.toml

Развёртывание на Fly.io

.env.example

Какие переменные окружения существуют

.mcp.json.example

Конфигурация клиента для копирования

USING-IT.md

Отдельная страница для передачи пользователям

guards.py

Аутентификация, лимит запросов, ограничения размера, логирование

tests/

Офлайн-тесты, API-ключ не требуется

.github/workflows/

CI: тесты, проверка запуска, сканирование секретов

Related MCP Connectors

Related MCP Servers