MCP GitHub Server
MCP GitHub Server
Analog-search quality candidate (PR #112): 2–8 formulations, safe explicit page continuations with fingerprint validation, README-scope advisories, accountable facet-coverage ordering and large-commit source-pin recovery. No exhaustive-GitHub or commercial-demand claim. Audit and acceptance. Tests run in the agent sandbox only; no VPS execution/deployment is authorized.
Расширяемый MCP HTTP-сервер с модульной архитектурой и автоматическим обнаружением инструментов. Изначально вырос из обёртки над GitHub API, сейчас — универсальный набор инструментов для агента.
Сервер реализует MCP Streamable HTTP transport (JSON-RPC 2.0 поверх POST /mcp).
📌 Source of truth
Что | Где источник правды |
Версия |
|
Список инструментов | рантайм-реестр: |
Схема инструмента |
|
Документация | ревизия 8 от 2026-10-15 |
Ревизия документации: 8 · 2026-10-15. Инкрементируется при каждом значимом изменении README/ROADMAP/TOOLS/SANDBOX. При расхождении доков и рантайма — прав рантайм (код), доки приводим к нему. Ревизия 4: добавлен раздел «Продакшен (Gunicorn + Caddy)». Ревизия 5: добавлен подраздел «Пошаговый деплой на Ubuntu VPS», а также Windows/Waitress и примечание про PEP 668/venv. Ревизия 6: синхронизированы roadmap, карта проекта и границы планируемого бинарного канала #88 → #89; это документация, не реализация этих задач. Ревизия 7: полный runtime/docs audit, stateless HTTP-контракт, OS-границы и автоматические inventory/link/example guards. Ревизия 8: завершённый production rollout, отдельный TEST-кандидат, HTTP-проверенная публикация Pages и ограниченная feasibility #88; upload API ещё не реализован.
Related MCP server: git-mcp
Статус проекта и новые задачи
Roadmap — приоритеты и проверяемые gates; карта проекта — архитектура и зависимости. Код в
main, кандидат в TEST и production — разные состояния.Новый файловый маршрут запланирован, не реализован: #88 (реальные bytes клиент → staging) → #89 (Release assets → Actions → проверяемый результат). Подробности и ограничения — в плане.
/data/...в среде клиента не является путём на MCP-сервере.run_command, локальные файловые API и серверныйpathне передают файл между средами. Малый synthetic client→TEST probe подтвердил сохранение bytes/size/hash через file-backed аргументы; это не готовый upload API и не доказательство доступности такого механизма во всех клиентах. Результат и ограничения.create_or_update_binary_fileсейчас декодирует base64 как UTF-8 и записывает файл в Git: это не универсальный ZIP/XLSX upload и не staging.download_artifactотносится к Actions artifacts, а не к Release assets.PR #87 — Draft, artifact attempt identity: не выдавать установку кандидата в TEST за завершённый live acceptance.
auto_fix_buildвmainотключён; безопасная замена — #86.Production обновлён по отдельному разрешению:
mcp-server.serviceзакреплён наb78b209cf5e8927c2c4bb9771d6ff0bafcad0cf6, 113 tools, опасные локальные категории выключены. TEST остаётся на кандидате #87. Снимок окружений и evidence. Новые commits/PR не разворачиваются автоматически.Эти планы не разрешают новые deployments, публикацию приватных файлов, изменение приватности репозитория, платные сервисы или реальные вычисления. GitHub Pages — отдельный статический сайт: после merge #70 deployment успешен, страницы проверены по HTTP; визуальный Mermaid на опубликованном сайте ещё не принят.
Возможности
Актуальный состав инструментов: list_my_tools на выбранном сервере и describe_tool(name); каталог — TOOLS.md. Инструменты разложены по подпакетам mcp_server/tools/. Каждый подпакет — независимая категория, которую можно включать и отключать отдельно.
🐙 github/ — GitHub API
Файлы, коммиты, ветки, PR (включая review-threads), issues, releases, tags, gists, Actions/workflows, search, security-алерты.
Группа | Инструменты |
Файлы |
|
Коммиты |
|
Ветки / сравнение |
|
PR |
|
Issues / метки |
|
Releases / Tags |
|
Gists |
|
Actions / Workflows |
|
Search |
|
Security |
|
Repo info / admin |
|
Batch |
|
Большие файлы.
get_file_contentsотдаёт файл целиком — для больших файлов клиент может обрезать ответ ([truncated]). Используйтеread_file_chunk(owner, repo, path, ref, offset, limit): жёстко ограниченный кусок строк (≤ 32 KB). Поиск по файлу —grep_file(...). Файл целиком без угадывания чанков —read_full_file(...)(сам подбирает размер, склеивает части, ставит(конец файла)либо предупреждение о бюджетеmax_bytes).Прямые ссылки на файл.
get_file_contents/read_full_fileв начале ответа возвращают🔗(blob) и📄(raw) ссылки.
🏗️ build/ — сборка и отладка (13)
watch_build, auto_fix_build, get_android_build_error, get_ios_build_error, get_run_logs_by_step, get_step_logs_via_checks, get_latest_workflow_error, get_workflow_run_logs, get_full_workflow_logs, get_workflow_by_file, list_workflow_runs, get_latest_run_id, get_workflow_run_steps
🌐 web/ — веб (4)
web_fetch, web_search (DuckDuckGo HTML, без API-ключа), rss_read, html_to_markdown
🧰 utils/ — утилиты и данные (15)
base64_encode, base64_decode, hash_text, json_format, json_query, uuid_generate, timestamp_now, date_convert, regex_test, text_diff, csv_parse, csv_generate, yaml_to_json, json_to_yaml, markdown_to_html
🧭 meta/ — мета-инструменты (2)
list_my_tools, describe_tool
🧠 synapse/ — находимость людей (ENABLE_SYNAPSE=1)
При ENABLE_SYNAPSE=1 зарегистрированы 14 инструментов: publish_profile, search_people, propose_contact, save_note, search_notes, index_github, submit_offer, submit_want, list_my_items, deactivate_item, model_me, find_my_match, draft_profile_from_dialog, report_match_outcome. Item/embedding-код уже в main; регистрация не доказывает качество matching или доступность настроенного provider. Без provider используется keyword fallback. Протокол — docs/synapse-protocol.md.
🔒 localfs/ — локальные файлы (4, по умолчанию выключено)
read_local_file, write_local_file, list_local_dir, search_in_files. Флаг ENABLE_LOCAL_TOOLS=1, корень LOCAL_TOOLS_ROOT. См. SANDBOX.md.
🔒 localgit/ — git в workspace (6, по умолчанию выключено)
git_status, git_log, git_diff, git_commit, git_push, git_pull. Тот же флаг.
🔒 shell/ — sandboxed shell / python (2, по умолчанию выключено)
run_command, run_python. Флаг ENABLE_LOCAL_SHELL=1; cwd ограничен LOCAL_TOOLS_ROOT, но исполняемый код имеет права пользователя сервера и может обращаться к другим доступным файлам/сети. Это не OS sandbox.
🔒 process/ — фоновые процессы (4, Linux-only runtime)
start_background, stop_process, process_status, tail_log. Тот же ENABLE_LOCAL_SHELL=1; Linux identity guard, группы процессов, bounded чтение логов. Контракт. См. SANDBOX.md.
Установка
git clone https://github.com/LeonidYasin/mcp-server.git
cd mcp-server
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e .На Ubuntu с PEP 668 не устанавливать пакет в системный Python. Для разработки в уже активированном venv:
python -m pip install -e ".[dev]"Для обычного запуска достаточно python -m pip install -e .; [dev] добавляет pytest для проверки проекта.
Запуск
Локально / для разработки
python -m mcp_server.serverПо умолчанию сервер слушает http://127.0.0.1:3001, MCP-эндпоинт — POST /mcp. Bind можно явно переопределить MCP_HOST/MCP_PORT. GET /health показывает версию/build, tool_count, список инструментов и факт наличия заголовка последнего запроса, но не сам токен. При внешнем доступе защищать и /health: он раскрывает диагностическую информацию.
⚠️ Это dev-режим. Внутри используется встроенный dev-сервер Werkzeug; это не production deployment boundary, независимо от режима обработки потоков. Для локальной работы и отладки — ок, для боевого сервера — нет (см. раздел «Продакшен» ниже).
Токен GitHub передаётся заголовком Authorization: Bearer <token>.
Продакшен (Gunicorn + Caddy)
Для боевого развёртывания используется классическая слоёная схема:
Интернет ──HTTPS(443)──▶ Caddy ──HTTP(127.0.0.1:3001)──▶ Gunicorn ──WSGI──▶ Flask appCaddy — принимает HTTPS, проверяет ключ клиента, проксирует на loopback.
Gunicorn — production WSGI-сервер: несколько воркеров, устойчивость к падениям, корректная обработка сигналов.
Flask app — сам код (
mcp_server.server:app), без изменений.
1. Установка зависимостей
pip install -e ".[prod]" # gunicorn (Linux/macOS)
# или, если extra ещё не заведён в pyproject.toml:
pip install -e . gunicorn2. Запуск через Gunicorn
# слушаем ТОЛЬКО локальный интерфейс — из интернета напрямую недоступно
gunicorn mcp_server.server:app \
--bind 127.0.0.1:3001 \
--workers 2 \
--timeout 120 \
--access-logfile - \
--error-logfile -Почему --bind 127.0.0.1: сервер не должен торчать в интернет сам по себе. Снаружи его закрывает Caddy, который терминирует TLS и аутентификацию. --workers 2 — достаточно для одного пользователя/агента; при росте нагрузки увеличивается до 2 × CPU + 1.
3. Caddy (TLS + аутентификация по ключу)
Caddyfile (минимальный рабочий конфиг):
mcp.example.com {
# ключ клиента Claude передаётся в отдельном заголовке,
# чтобы не конфликтовать с Authorization: Bearer <github_token>,
# который уходит дальше в GitHub API
@authorized header X-API-Key "<СЕКРЕТНЫЙ_КЛЮЧ_КЛИЕНТА>"
handle @authorized {
reverse_proxy 127.0.0.1:3001
}
handle {
respond "Unauthorized" 401
}
}mcp.example.com Caddy сам получит и будет продлевать TLS-сертификат Let's Encrypt. Запросы без правильного X-API-Key отсекаются на входе и до приложения не доходят.
4. systemd-юнит (автозапуск)
/etc/systemd/system/mcp-server.service:
[Unit]
Description=MCP GitHub Server
After=network.target
[Service]
Type=simple
User=mcp
WorkingDirectory=/opt/mcp-server
ExecStart=/opt/mcp-server/.venv/bin/gunicorn mcp_server.server:app \
--bind 127.0.0.1:3001 --workers 2 --timeout 120
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now mcp-server
sudo systemctl status mcp-server5. Клиент (например, Claude как кастомный коннектор)
URL:
https://mcp.example.com/mcpRequest header:
X-API-Key: <СЕКРЕТНЫЙ_КЛЮЧ_КЛИЕНТА>GitHub-токен по-прежнему передаётся в
Authorization: Bearer <github_token>и доходит до приложения как есть — Caddy его не трогает.
Почему не использовать dev-сервер в production.
main()по умолчанию использует loopback (MCP_HOST=127.0.0.1,MCP_PORT=3001,debug=False), но это не полноценная граница безопасности. Нужны production WSGI, TLS, аутентификация на proxy и OS policy. ЯвныйMCP_HOST=0.0.0.0без такой защиты опасен; GitHub PAT не заменяет отдельную авторизацию доступа к MCP.
6. Windows: Gunicorn не подходит — используйте Waitress
Gunicorn не работает на Windows. Он зависит от POSIX-модуля fcntl, которого в Windows нет:
ModuleNotFoundError: No module named 'fcntl'Для Windows production-запуска есть Waitress — чистый Python WSGI-сервер, многопоточный, без POSIX-зависимостей и с официальной поддержкой Windows.
pip install waitress
waitress-serve --host=127.0.0.1 --port=3001 --threads=4 mcp_server.server:appОстальная схема не меняется: Waitress так же слушает 127.0.0.1:3001 за reverse proxy (Caddy/Nginx/IIS), а Caddy терминирует TLS и проверяет X-API-Key.
Платформа | WSGI-сервер | Причина |
Linux / macOS | Gunicorn | стандарт де-факто, multi-process |
Windows | Waitress | чистый Python, multi-thread, без |
Для локального HTTP smoke на Windows достаточно dev-сервера. Это не заменяет pytest, Linux process-manager tests, CI и live gates; process tools требуют Linux
/proc. Waitress — вариант production WSGI для Windows, не замена OS-изоляции.
7. Пошаговый деплой на Ubuntu VPS (проверено вживую)
Ниже — последовательность, реально отработанная на Ubuntu 24.04 VPS (2026-09-27): Gunicorn + Caddy + DuckDNS, снаружи проверено curl.
Разделение ролей. Команды помечены: # root — под root (или через sudo), $ mcp — под сервисным пользователем. Сервисный пользователь запускает приложение, но не имеет прав на systemd/apt/Caddy.
Шаг 1. Сервисный пользователь (под root).
Пользователь создаётся с домашней папкой и shell, но без sudo. Это важно: у него должны работать локальные инструменты (localfs, localgit, shell, работа с БД), поэтому нужен $HOME и /bin/bash. Ограничение только одно — нет прав за пределами $HOME и нет sudo.
# root
adduser --disabled-password --gecos "" mcp
# опционально: убедиться, что НЕ в группе sudo
deluser mcp sudo 2>/dev/null || trueШаг 2. Установка venv-пакетов (под root).
Ubuntu 24.04 блокирует pip install в системный Python (PEP 668, externally-managed-environment). Поэтому ставим через venv:
# root
apt install -y python3-venv python3-fullШаг 3. Проект и venv (под сервисным пользователем).
# mcp
cd ~
git clone https://github.com/LeonidYasin/mcp-server.git
cd mcp-server
python3 -m venv .venv
.venv/bin/pip install -e . gunicornКлючевое: pip — именно из venv (.venv/bin/pip), а не системный. И venv создаётся под тем же пользователем, который будет запускать сервис — чтобы файлы принадлежали ему.
Шаг 4. systemd-юнит (под root).
/etc/systemd/system/mcp-server.service:
[Unit]
Description=MCP GitHub Server
After=network.target
[Service]
Type=simple
User=mcp
Group=mcp
WorkingDirectory=/home/mcp/mcp-server
ExecStart=/home/mcp/mcp-server/.venv/bin/gunicorn mcp_server.server:app \
--bind 127.0.0.1:3001 --workers 2 --timeout 120
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target# root
systemctl daemon-reload
systemctl enable --now mcp-server
systemctl status mcp-server # ожидаем: active (running)Проверка изнутри (можно под любым пользователем):
curl -s http://127.0.0.1:3001/health | head -c 200Должен вернуться JSON с tool_count и списком инструментов.
Шаг 5. Домен.
Нужен публичный домен, указывающий на IP VPS. Бесплатный вариант — DuckDNS: регистрируешь поддомен имя.duckdns.org, указываешь IP VPS. Проверка:
dig +short имя.duckdns.org # должен вернуть публичный IP VPSДомен обязателен: клиенты (в т.ч. Claude как кастомный коннектор) требуют URL вида https://домен, а Let's Encrypt выдаёт сертификат на домен. GitHub Pages для этого не подходит — он отдаёт только статику и не умеет проксировать на VPS.
Шаг 6. Caddy: HTTPS + аутентификация по ключу (под root).
Сгенерировать ключ клиента:
# root
openssl rand -hex 32/etc/caddy/Caddyfile:
имя.duckdns.org {
# ключ клиента в отдельном заголовке, чтобы не конфликтовать
# с Authorization: Bearer <github_token>, который уходит в GitHub API
@authorized header X-API-Key "<СЕКРЕТНЫЙ_КЛЮЧ_КЛИЕНТА>"
handle @authorized {
reverse_proxy 127.0.0.1:3001
}
handle {
respond "Unauthorized" 401
}
}# root
caddy validate --config /etc/caddy/Caddyfile
systemctl reload caddy
systemctl status caddy # ожидаем: active (running)Caddy сам получит и будет продлевать сертификат Let's Encrypt. Запросы без правильного X-API-Key отсекаются на входе (401) и до приложения не доходят.
Шаг 7. Проверка снаружи (с любой машины, не с VPS).
# без ключа — ожидаем 401
curl -i https://имя.duckdns.org/health
# с ключом — ожидаем 200 и JSON
curl -i -H "X-API-Key: <СЕКРЕТНЫЙ_КЛЮЧ_КЛИЕНТА>" https://имя.duckdns.org/healthЗаголовок Server: gunicorn и Via: 1.1 Caddy в ответе подтверждают, что цепочка Caddy → Gunicorn работает.
Шаг 8. Подключение клиента (например, Claude как кастомный коннектор).
URL:
https://имя.duckdns.org/mcpRequest header:
X-API-Key: <СЕКРЕТНЫЙ_КЛЮЧ_КЛИЕНТА>
GitHub-токен по-прежнему передаётся в Authorization: Bearer <github_token> и доходит до приложения как есть — Caddy его не трогает.
Шаг 9. Файрвол (опционально, под root).
Gunicorn слушает только 127.0.0.1, поэтому порт 3001 извне недоступен и без файрвола. Как дополнительный слой:
# root
ufw allow 22/tcp # SSH — СНАЧАЛА, иначе потеряешь доступ
ufw allow 80/tcp # HTTP-01 challenge для Let's Encrypt
ufw allow 443/tcp # HTTPS
ufw enable
ufw statusПорт 3001 в UFW открывать не нужно.
Включение локальных инструментов
export ENABLE_LOCAL_TOOLS=1 # localfs + localgit
export ENABLE_LOCAL_SHELL=1 # shell + process (опасные OS-права; только изолированная среда)
export ENABLE_SYNAPSE=1 # synapse
export LOCAL_TOOLS_ROOT=/workspace # whitelist-корень (по умолчанию ~/workspace)
python -m mcp_server.serverПодключение к DeepSeek++
URL:
http://127.0.0.1:3001/mcpТип: HTTP
Заголовок:
Authorization: Bearer <ваш_github_token>
Транспорт: используйте клиентский режим MCP Streamable HTTP, поддерживающий JSON-ответы на
POST /mcp. Текущая реализация stateless: не выдаётMcp-Session-Id, не поддерживает SSE-поток (GET /mcpвозвращает 405) и не реализует resumable sessions. Названия режимов в конкретном клиенте не гарантируют совместимость; клиент, требующий SSE или обязательный session ID, нужно проверять отдельно. Фактический HTTP-контракт и offline smoke.
📚 Документация и Skills
Файл | Что внутри |
этот файл: установка, запуск, обзор подпакетов, Source of truth | |
каталог по подпакетам, контракты и явно обозначенные ограничения | |
дорожная карта: текущие issues/PR, зависимости #88 → #89, сделанные батчи и backlog | |
карта архитектуры, доверительных границ и статусов разработки | |
план #88 → #89: клиентские bytes, staging, Release assets, Actions и критерии приёмки | |
границы localfs/localgit/shell/process, уровни 1–3 и ограничения | |
stateless HTTP-контракт, token gate и безопасный offline smoke | |
датированный снимок production/TEST, rollout evidence и оставшиеся gates | |
воспроизводимые проверки каталога, ссылок, тестов и сборки | |
автоматически сверяемые default/all-enabled профили реестра | |
JSON-схема обмена (item: offer/want, profile, contact, exchange) | |
Skill для ИИ-агентов: безопасный workflow работы с GitHub через MCP |
Skills (
docs/skills/) — это инструкции для ИИ-агентов, как правильно и безопасно пользоваться инструментами этого сервера. Каждый Skill — отдельная папка сSKILL.md. Новые Skills добавляйте рядом и упоминайте здесь.
Структура проекта
mcp-server/
├── pyproject.toml # dynamic version из mcp_server/__init__.py
├── README.md
├── ROADMAP.md
├── SANDBOX.md
├── TOOLS.md # полный каталог инструментов
├── docs/
│ ├── http-transport.md # HTTP-контракт и ограничения
│ ├── deployment-status.md # production/TEST и evidence rollout
│ ├── validation.md # проверка документации и сборки
│ ├── tool-inventory.json # проверяемый snapshot реестра
│ ├── project-map.md # архитектура, границы и статусы
│ ├── binary-transfer-plan.md # план #88 → #89 (не готовый API)
│ ├── synapse-protocol.md # JSON-схема item/profile/contact/exchange
│ └── skills/ # Skills для ИИ-агентов (см. ниже)
└── mcp_server/
├── server.py # Flask HTTP-сервер (MCP transport, token handling)
├── core/
│ ├── tool.py # Tool dataclass
│ └── registry.py # ToolRegistry + @mcp_tool
└── tools/
├── build/ # сборка и отладка
├── github/ # GitHub API
├── localfs/ # локальные файлы (ENABLE_LOCAL_TOOLS)
├── localgit/ # git в workspace (ENABLE_LOCAL_TOOLS)
├── meta/ # list_my_tools, describe_tool
├── process/ # фоновые процессы (ENABLE_LOCAL_SHELL, Linux)
├── shell/ # shell/python (ENABLE_LOCAL_SHELL)
├── synapse/ # находимость людей (ENABLE_SYNAPSE)
├── utils/ # утилиты и данные
└── web/ # web_fetch, web_search, rss, htmlКак добавить новый инструмент
Шаг 1. Создайте файл в нужном подпакете
Учебный пример формы декоратора на существующем create_branch (не создавайте второй tool с тем же именем — в реестре names должны быть уникальными):
"""MCP tool: create_branch - создаёт новую ветку."""
from mcp_server.core.registry import mcp_tool
from mcp_server.tools.github.client import GitHubClient
@mcp_tool(
name="create_branch",
description="Создаёт новую ветку в репозитории",
parameters={
"owner": {"type": "string", "description": "Владелец репозитория"},
"repo": {"type": "string", "description": "Имя репозитория"},
"branch": {"type": "string", "description": "Имя новой ветки"},
"from_branch": {"type": "string", "description": "Источник (по умолчанию main)"},
},
required=["owner", "repo", "branch"],
)
def create_branch(client: GitHubClient, owner: str, repo: str, branch: str, from_branch: str = "main") -> dict:
"""Создать новую ветку."""
...Шаг 2. Подключите файл в __init__.py подпакета
Реестр (mcp_server/core/registry.py) регистрирует только то, что явно импортировано в mcp_server/tools/<подпакет>/__init__.py. Без импорта функция не станет инструментом.
Шаг 3. Обновите доки
Добавьте инструмент в TOOLS.md и, если нужно, в этот README. Обновите snapshot (python scripts/check_docs.py --write-inventory), проверьте diff и выполните python scripts/check_docs.py + python -m pytest -q. Inventory regeneration не заменяет review: планируемые API в snapshot не включать. Инкрементируйте ревизию документации в блоке Source of truth. См. validation.
This server cannot be deployed
Maintenance
Related MCP Connectors
Create, deploy, and operate MCP servers directly from your GitHub repositories.
GitHub MCP — wraps the GitHub public REST API (no auth required for public endpoints)
A MCP server built for developers enabling Git based project management with project and personal…
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- -licenseNot gradedqualityAmaintenanceMCP Server for the GitHub API, enabling file operations, repository management, search functionality, and more.124,024 npm91,671MIT
- FlicenseNot gradedqualityDmaintenanceStandalone MCP server for GitHub that enables repository management, branch operations, pull request handling, and commit retrieval via tools listed in the README.1-
- AlicenseBqualityDmaintenanceMCP (Model Context Protocol) server for GitHub API integration. This server provides comprehensive tools for interacting with GitHub repositories, issues, pull requests, branches, and code search through a unified interface.156 npmMIT
- AlicenseNot gradedqualityBmaintenanceA lightweight MCP server that exposes GitHub operations as tools over HTTP, enabling any MCP-compatible client to interact with GitHub repositories without a built-in connector.1MIT