- Go 98.6%
- Dockerfile 1.3%
|
|
||
|---|---|---|
| cmd/server | ||
| docs | ||
| internal | ||
| .gitignore | ||
| .woodpecker.yml | ||
| config.yml.example | ||
| continue.sh | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| README.md | ||
mcp-http — MCP-сервер для HTTP-запросов
Модуль: git.ymnuktech.ru/ymnuk/mcp-http
MCP-сервер, выполняющий HTTP-запросы с поддержкой whitelist/blacklist фильтрации адресов, пользовательских TLS-сертификатов и гибкого логирования. Инструмент http_request доступен через протокол MCP как tools/call.
Возможности
- Выполнение HTTP-запросов всех методов (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
- Whitelist/Blacklist фильтрация (домены, wildcard, IP, CIDR)
- TLS: пользовательские CA-сертификаты + опция
tls_insecure_skip_verifyдля самоподписанных - Кастомные заголовки и User-Agent с приоритетом источника
- Определение типа контента ответа (text/image/audio/binary)
- JSONL логирование через slog (
debug,info,warn,error,off) - Два транспорта:
stdio(по умолчанию) иhttp(streamable over HTTP) - Конфигурация через CLI → ENV → YAML с автоматическим поиском путей
- Pinned-режим: локдаун на один домен/IP (
base_url) + обязательные заголовки, клиент передаёт только path
Быстрый старт
# Сборка
go build -o mcp-http ./cmd/server
# stdio + логирование
./mcp-http --log-level debug --config ./config.yaml
# HTTP-сервер
./mcp-http --transport http --http-addr :8080 --tls-insecure-skip-verify
Docker
docker run -p 8080:8080 \
-v ./config.yml:/config.yml \
git.ymnuktech.ru/ymnuk/mcp-http:v0.1.0 \
--config /config.yml
Docker Compose
services:
mcp-http:
image: git.ymnuktech.ru/ymnuk/mcp-http:v0.1.0
command: ["--config", "/config.yml"]
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
networks: [mcp-network]
restart: unless-stopped
configs:
- source: mcp-http-v1.yml
target: /config.yml
configs:
mcp-http-v1.yml:
file: ./config/mcp-http.yml
Конфигурация
Приоритет источников (от высшего к низшему)
- CLI флаги (
--whitelist,--log-levelи т.д.) - ENV переменные (
MCP_HTTP_USER_AGENT,MCP_HTTP_LOG_LEVELи т.д.) - Конфиг файл YAML/JSON
- Значения по умолчанию (в коде)
go-simple-args применяет значения последовательно — последние побеждают первые.
Поиск конфигурационного файла
Приоритет поиска (первый найденный используется):
--config <path>— явный CLI флаг$MCP_HTTP_CONFIG— переменная окружения./config.yaml/./config.yml/./config.json— рабочая директория~/.config/mcp-http/config.yaml— домашняя директория пользователя/etc/mcp-http/config.yaml— системный путь
Пример конфига (config/example.yaml)
# User-Agent для всех HTTP-запросов (переопределяется CLI/ENV флагом)
user_agent: "mcp-http/1.0"
# Whitelist — разрешенные домены, IP или CIDR подсети
whitelist:
- example.com
- "*.internal.local"
- 192.168.0.0/16
- 10.0.0.1
# Blacklist — запрещённые домены, IP или CIDR подсети
blacklist:
- evil.com
- "172.16.0.0/12"
# Пути к пользовательским CA сертификатам (TLS)
ca_cert_files:
- /etc/ssl/certs/my-ca.pem
# Игнорировать ошибки TLS (самоподписанные, недействительные сертификаты)
tls_insecure_skip_verify: false
# Базовые заголовки для всех запросов
headers:
Authorization: "Bearer <token>"
# Уровень логирования: debug, info, warn, error, off
log_level: "debug"
# Путь к файлу логов (если пустой — логи в stderr/stdout)
log_file: "/var/log/mcp-http.jsonl"
# Транспорт и HTTP-сервер для http-режима
transport: "stdio"
http_server:
enabled: true
addr: ":8080"
CLI флаги и ENV переменные
| Флаг | Переменная окружения | Описание | По умолчанию | Тип |
|---|---|---|---|---|
--config, -c <path> |
MCP_HTTP_CONFIG |
Путь к YAML/JSON конфигу | автопоиск (см. выше) | string |
--user-agent, --ua <string> |
MCP_HTTP_USER_AGENT |
User-Agent для HTTP-запросов | "mcp-http/0.1.0" |
string |
--log-level <level> |
MCP_HTTP_LOG_LEVEL |
Уровень логирования: debug/info/warn/error/off | "off" |
enum |
--log-file <path> |
MCP_HTTP_LOG_FILE |
Путь к файлу логов (JSONL) | пустой (stderr/stdout) | string |
--transport <type> |
MCP_HTTP_TRANSPORT |
Транспорт: stdio/http | "stdio" |
enum |
--tls-insecure-skip-verify |
MCP_HTTP_TLS_INSECURE_SKIP_VERIFY |
Пропускать валидацию TLS (самоподписанные) | false |
bool |
--whitelist, -w <host> |
MCP_HTTP_WHITELIST |
Разрешённые адреса (можно повторять) | пустой | string[] |
--blacklist, -b <host> |
MCP_HTTP_BLACKLIST |
Запрещённые адреса (можно повторять) | пустой | string[] |
--ca-certs <path> |
MCP_HTTP_CA_CERTS |
Пути к CA-сертификатам PEM (можно повторять) | пустой | string[] |
--header, -H <kv> |
MCP_HTTP_HEADERS |
Базовый заголовок key=value (можно повторять) | пустой | string[] |
--http-enable |
MCP_HTTP_HTTP_ENABLE |
Включить HTTP-сервер | auto по --transport |
bool |
--http-addr <host:port> |
MCP_HTTP_ADDR |
Адрес слушания для HTTP-режима | ":8080" |
string |
--base-url <url> |
MCP_HTTP_BASE_URL |
Базовый адрес — включает pinned-режим | пустой | string |
--alias <name> |
MCP_HTTP_ALIAS |
Имя инструмента в pinned-режиме (иначе авто-имя из хоста) | пустой | string |
--mandatory-header, -hm <kv> |
MCP_HTTP_MANDATORY_HEADERS |
Обязательный заголовок key=value (можно повторять), клиент не может перезаписать | пустой | string[] |
--version, -v |
— | Версия и выход | — | flag |
Пример запуска с TLS и whitelist
./mcp-http \
--config ./config.yaml \
--tls-insecure-skip-verify \
--whitelist api.internal.local \
--ca-certs /opt/certs/my-ca.pem \
--log-level debug
Pinned-режим
Если задан base_url, сервер выполняет запросы только к этому хосту. Инструмент http_request не регистрируется — вместо него появляется единственный инструмент http_request_path, и клиент передаёт только path (домен ему не виден и не может быть изменён).
# example.yml.example (фрагмент)
base_url: "http://192.168.0.18:1880" # включает pinned-режим
alias: "node_red" # имя инструмента (иначе авто-имя из хоста)
mandatory_headers: # нельзя перезаписать клиентом
Authorization: "Bearer <secret>"
Имя инструмента генерируется из base_url, если alias не задан:
| Вход | Имя |
|---|---|
https://192.168.0.24 |
192_168_0_24 |
http://192.168.0.18:1880 |
192_168_0_18_1880 |
http://langflow:7860 |
langflow_7860 |
http://node-red:1880 |
node_red_1880 |
| не парсится | pinned_request |
Входные параметры http_request_path
| Параметр | Тип | Обязательный | По умолчанию | Описание |
|---|---|---|---|---|
path |
string | Да | — | Путь на базовом хосте, напр. /v1/users?limit=10 (без хоста и схемы) |
method |
string | Нет | "GET" |
HTTP метод |
headers |
map[string]string | Нет | {} |
Доп. заголовки (не перезаписывают обязательные) |
body |
string | Нет | "" |
Тело запроса |
timeout |
int | Нет | 30 |
Таймаут в секундах |
Обязательные заголовки (mandatory_headers) всегда побеждают заголовки из запроса и не попадают в описание инструмента — LLM не видит секреты. Выходной формат такой же, как у http_request.
Инструмент MCP http_request
Входные параметры (CallToolRequest.params)
| Параметр | Тип | Обязательный | По умолчанию | Описание |
|---|---|---|---|---|
url |
string | Да | — | URL для HTTP-запроса |
method |
string | Нет | "GET" |
HTTP метод: GET/POST/PUT/PATCH/DELETE/HEAD/OPTIONS |
headers |
map[string]string | Нет | {} |
Кастомные заголовки поверх конфига (request priority) |
body |
string | Нет | "" |
Тело запроса для POST/PUT/PATCH |
timeout |
int | Нет | 30 |
Таймаут в секундах |
Выходные параметры (structuredContent)
| Поле | Тип | Описание |
|---|---|---|
status_code |
int | HTTP код ответа (200, 404, 500 и т.д.) |
headers |
map[string][]string | Все заголовки ответа |
body |
string | Тело ответа: для text/json — raw содержимое, для images/audio — метаданные [image/png, 256 KB] |
content_type |
string | MIME Content-Type (из Response Headers) |
duration_ms |
float64 | Длительность запроса в миллисекундах |
is_image |
bool | true если ответ — изображение |
Логирование MCP-запросов (middleware)
Middleware логирует все входящие запросы через slog:
| Уровень | Поля | Описание |
|---|---|---|
| INFO (всегда) | method, tool, args_bytes/params |
Входящий MCP-запрос |
| DEBUG (после) | duration_ms, error, result/content_size/image_size_bytes/result_type |
Исходящий ответ |
params > 512 байт логируется только как
"512+ bytes"(без содержимого). Текст ответа < 256 символов копируется полностью, остальное — вcontent_size: N. Images — вimage_size_bytes.
Сборка и CI/CD
Локальная сборка
go build -o mcp-http ./cmd/server
# Сборка с версией (ldflags)
CGO_ENABLED=0 GOOS=linux go build \
-ldflags="-s -w -X git.ymnuktech.ru/ymnuk/mcp-http/internal/version.Version=1.0.0" \
-o mcp-http ./cmd/server/
./mcp-http --version
# → mcp-http 1.0.0 (commit: abc123, built: 2026-08-10T00:00:00Z)
Docker образ
Двухэтапная сборка (builder + alpine):
- Builder:
golang:1.26.5-alpineс CA-сертификатами и timezone - Final:
alpine:3.21— минимальный образ с CA certs, tzdata, usernobody:nogroup - Порт: 8080
- Default transport:
http(поэтому не нужно явно указывать в CMD)
Woodpecker CI/CD (.woodpecker.yml)
Pipeline запускается только по тегу на ветке main:
| Этап | Назначение | Делает |
|---|---|---|
build-binary |
amd64 бинарник | Сборка go-binary с version injection через ldflags |
build-docker |
Multi-arch образ | docker-buildx → push на git.ymnuktech.ru/ymnuk/mcp-http:{tag} |
release |
Pypi/Gitea release | Загрузка бинарника в релиз |
Тестирование
# Запуск всех тестов с покрытием
go test ./... -cover
# Покрытие по пакетам:
# internal/config 81.7%
# internal/filter 80.7%
# internal/httpclient 75.4%
# internal/logger 90.5%
# internal/middleware (middleware-based)
# Итого ~81.5% покрытие по коду, 51 тест
Документация проекта
| Файл | Описание |
|---|---|
| Зависимости | Полная документация по всем библиотекам: go-simple-args, go-yaml, go-sdk/mcp v1.7.0, godotenv |
| Проект | Архитектура, приоритеты конфигов, API tool, логирование, транспорты, whitelist/blacklist engine |
| Roadmap | План разработки с декомпозицией на этапы и задачи (~15-20 часов) |
Зависимости
git.ymnuktech.ru/ymnuk/go-simple-args v0.1.1 — CLI / ENV / config files (auto precedence)
github.com/goccy/go-yaml v1.19.2 — YAML parsing
github.com/modelcontextprotocol/go-sdk v1.7.0 — MCP server/sdk + content types
github.com/joho/godotenv v1.5.1 — .env file loading