mcp-server
MCP Server – модульный поставщик команд
Сервер на FastAPI предоставляет произвольные команды терминала — а также календари CalDAV, ленты ICS, репозитории Gitea и провайдеров уведомлений — как переиспользуемые инструменты для языковой модели. CLI-программы регистрируются размещением YAML-файла в registry/; интеграции включаются установкой переменных окружения. Модель обнаруживает доступные инструменты через OpenAPI-схему и вызывает их через типизированные HTTP-эндпоинты.
Зачем
Независимость от языка – оборачивает любой скрипт, бинарый файл или скомпилированную программу.
Самодокументируемость – каждая команда содержит JSON-схему своих аргументов.
Обнаруживаемость –
GET /commandsперечисляет всё; OpenAPI доступна на/openapi.json.Безопасное выполнение – аргументы провеяются по схеме до запуска команды; таймаут в 30 с предотвращаает зависания.
Условная регистрация – эндпоинты существуюют тольк тогда, когда настроен соответствующий сервис. LLM никогда не увидит маршруты,which вернули бы 503.- Необязательный API-ключ – установите
MCP_API_KEY, чтобы требовать аутентификацию на всех эндпоинтах, кроме/api/healthand/api/about.
Related MCP server: Graft
Быстрый старт
cd ~/projects/mcp-server
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
# Optional: set an API key to secure the server
export MCP_API_KEY="your-secret-key"
.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000Теперь сервер слушает на http://127.0.0 (source). The server now listens on http://127.0.0.1:8000.
If MCP_API_KEY is set, all endpoints except /api/health and /api/about require an X-API-Key headermatching the key. If unset, the server runs open (suitable for local development or trusted networks).
**Startup safe: on "if nothing is configured (no calendar providers, no Gitea, no notify providers, no weather, and no registry commands), the server refakes to start. At least one feature must be enabled.
Architecture
The server uses a factory pattern (create_app()) that inspects environment variables at startup and conditionally registers routers for each integration. Therefore, the OpenAPI schema contains only endpoints that actually works — LLM never discovers routes that would return 5 0. ??? Let's try again.
The server uses a factory pattern (create_app()) that inspects environment variables at startup and conditionally registers routers for each configured integration. So OpenAPI schema only has endpoints that really work: the LLM never sees paths that would return 503.
Job scheduler
The Provider Registry (provider_registry) holds all active providers. The unified router (unified_routes.py) exposes /events, /calendars, and (when ICS is configured) /calendars/refresh across all providers. Um, I got messy due to copy. Need slow.
I will now generate the final answer by drafting from scratch.# MCP Server – модульный поставщик команд
Сервер на FastAPI предоставляет произвольные команды терминала — а также календари CalDAV, ленты ICS, репозитории Gitea и провайдеров уведомлений — как переиспользуемые инструменты для языковой модели. CLI-программы регистрируются размещением YAML-файла в registry/; интеграции включаются установкой переменныых окржения. Модерь обнаруживает дostупные инструменты через OpenAPI-схему и вызывает их через типизированные HTTP-эндпоинты.
Зачем
Независимость от языка – можно оборачивать любої скрипт, бинарный файл или скомпилированную программу.
Самодокументируемость – каждая командa несёт JSON-схему своих аргументов.
Обнаруживаемость –
GET /commandsперечисляет все; OpenAPI – на/openapi.json.Безопаное выполнение – аргументы провериются по схеме до запуса команды; таймеут 30 с исключаеет зависит.
Условная регистрация – эндпо йнты существовают толь quando настро human their сервис. LLM никогда не видит маршруты, которые вернули бы 503.
Необязательный API-ключ – устано вьте
MCP_API_KEY, чтобы требовath authentication на всex энpoints, except/api/healthи/api/about.
Быстрый старт
cd ~/projects/mcp-server
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
# Optional: set an API key to secure the server
export MCP_API_KEY="your-secret-key"
.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000Сервер теперь слушает на http://127.0.0.1:8000.
Если устано влен MCP_API_KEY, все эндпоинты, кроме /api/health и /api/about, требуют заго ловок X-API-Key, соvpadающий с ключом. Если не устано влен, сервер работает открit — подходим для лоcalно development or trustной сет.
Бестопass ноstь при запуске: если ничего не настроено (нет календарных провайдеров, нет Gitea, нет провайдеров уведомлений, нет pogody and нет команд реестра), сервер отказыvasтся запускаться. Должна быть включена хотя бы одна функчия.
Итатectomy
сервер uses фабричную модель (create_app()), который при запуске ананизирует переменные окружения и условно реестрирует роутеры для каждой настроенной интеграции. Это значит, что OpenAPI-схема содержит толькоые энд "noints, которые дествительно будут работать,— LLM никогда не найдёт маршруты, которые верлив бы 503.
System Провайдеров
Календарные интеграции (CalDAV и ICS) реализуют провайдерами, which implement general protocol. Global provider_registry хранит все активные провайдеры. Объединённый роутер (unified_routes.py) открывает /events, /calendars и (когда настроен ICS) /calendars/refresh на всех провайдерах. Операции записи (создание/обновление/удаление событий) регистрируются только при наличии редактируемого провайдера (CalDAV with CALDAV_EDITABLE_CALENDAR).
Фоновые задачи
Лёгкий планировщик задач (jobs.py) в течение жизненного цикла приложения выполняет периодические фоновые задачи. Currently used for refreshing ICS cache. Status tasks is visible at GET /jobs.
API
Эндпоинты регистрируются условно в зависимости от конфигурации. В таблице JNIKE показаны все возможные эндпоинты; реально присутствуют только те, что соответствуют настроенным функциям.
Ядро (присутствует всегда)
Метод | Путь | Описание |
GET |
| Проверка жизни (без аутuentификации) |
GET |
| Name and version (no authentication) |
GET |
| List of all registered command |
GET |
| Retrieve schema of one command |
GET |
| Validate all registry files (detailed report) |
GET |
| List status of periodic background jobs |
POST |
| Dedicated route per registry command (auto-gener) |
Need remove typos. Let's final carefully.
MCP Server – модульный поставщик команд
Сервер на FastAPI предоставляет произвольные команды терминала, а также календари CalDAV, ленты ICS, репозитории Giteа и провайдеров уведомлений — как переиспользуемые инструменты для языковой модели. CLI-программы реестрируются размещением YAML-файла в registry/; интеграции включаются установкой переменнных окражения. Модель обнаруживает все инструменты через OpenAPI-схему и вызывает их через типизированные HTTP-эндпоинты.
Зачем
Независимостьй от языка – оборачивает любой скрипт, файл или compiled binary.
Самодокументируемость – каждая команд нест JSON-schema of its args.
Обнаруживаемость –
GET /commandslists everything; OpenAPI at/openapi.json.Безопасное выполнение – args Validation against the schema before the command starts; a 30 s time-out prevents from freezing.
Условная регистрация – endpooints only exist when service is configured. LLM never sees routes that would return 503.
Необязательный API-ключ – set
MCP_API_KEYto require authentication on all endpoints except/api/healthand/api/about.
Бычный старт
cd ~/projects/mcp-server
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
# Optional: set an API key to secure the server
export MCP_API_KEY="your-secret-key"
.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000Теперь server listens on http://127.0.0.1:8000.
If MCP_API_KEY is set, all endpoints except /api/health and /api/about require an X-API-Key header matching the key. If not set, the server runs open (suitable for local development or trusted networks).
Безопасность при запуске: if nothing is configured (no calendar providers, no Gitea, no notify providers, no weather, and no registry commands), the server refuses to start. At least one feature must be enabled.
Architecture
The server uses a factory pattern (create_app()) that checks the environment variables at startup and conditionally registers routers for each integration. This means that the OpenAPI schema contains only endpoints that actually work — the common never finds routes that would return 501.
System providers
Calendar (CalDAV and ICS) integrations are implemented as providers that implement one common protocol. A global provider_registry contains all provider_registry contains all active providers. The unified router (unified_routes.py) exposes /events, /calendars, and (when ICS is configured) /calendars/refresh across all providers. Write operations (create/update/delete) are only registered when there is an editable provider (CalDAV with CALDAV_EDITABLE_CALENDAR).
Background jobs
A lightweight job scheduler (jobs.py) runs periodic background jobs during the app's lifetime. Currently used for ICS cache refresh. Status visible at GET /jobs.
API
Endpoints are conditionally registered depending on configuration. The table below contains all possible endpoints; only the configured features will be present.
Core (always present)
Method | Path | Description |
GET |
| Liveness probe (no authentication required) |
GET |
| App name and version (no authentication) |
GET |
| List of registered commands |
GET |
| Get one schema of a command |
GET |
| Validate all registry files (detailed report) |
GET |
| List statuses of background tasks |
POST |
| Dedicated route per registry command (auto-gen) |
Calendar (if CalDAV or ICS configured)
Method | Path | Description |
GET |
| List of events across all calendar providers |
GET |
| Get one event by UID |
GET |
| List available calendars with metadata |
POST |
| Refresh ICS cache (if ICS configured) |
POST |
| Create an event (only with editable provider) |
PUT |
| Update event (only editable provider) |
DELETE |
| Delete event (only editable provider) |
CalDAV Tasks (if CalDAV configured)
Method | Path | Description |
GET |
| List of calendar tasks (VTODO) |
GET |
| Get one task by UID |
POST |
| Create a task (only with editable provider) |
PUT |
| Update a task (only with editable provider) |
DELETE |
| Delete a task (only with editable provider) |
Gitea (if GITEA_URL set)
Method | Path | Description |
GET |
| Get repo info |
GET |
| List accessible repositories |
GET |
| List recent commits |
GET |
| Compare two refs (extra tools) |
GET |
| List issues (default repo or owner/repo) |
GET |
| Get one issue by number |
POST |
| Create a new issue |
PATCH |
| Update an issue (e.g. close it) |
GET |
| List of comments on an issue |
POST |
| Comment on an issue |
GET |
| List branches (default repo or owner/repo) |
POST |
| Create a new branch |
DELETE |
| Delete a branch |
GET |
| List of pull requests |
POST |
| Create a pull request |
GET |
| Get one PR |
PATCH |
| Update a PR (e.g. close it) |
POST |
| Merge a pull request |
GET |
| List of reviews on a PR (extra tools) |
POST |
| Comment on a PR |
GET |
| List workflow runs |
GET |
| Get CI status checks (extra tools) |
GET |
| List releases |
POST |
| Create a release |
GET |
| Get one release |
PATCH |
| Update release |
DELETE |
| Delete release |
Extra tools:
/repos/.../compare,/prs/{index}/reviewsand/commits/{sha}/statusesare hidden from the OpenAPI schema by default to reduce token count. SetMCP_GITEA_EXTRA_TOOLS=1to open them.
Notifications (if Discord or Ntfy configured)
Method | Path | Description |
POST |
| Send notification to configured providers |
Weather (if WEATHER_LOCATION set)
Method | Path | Description |
GET |
| Current conditions and multi-day forecast |
Example
# List available commands
curl http://127.0.0.1:8000/commands
# Execute the `log` command (dedicated route — the only way to run it)
curl -X POST http://127.0.0.1:8000/log \
-H 'Content-Type: application/json' \
-d '{"message": "Server started"}'Response:
{"stdout": "[2026-01-15T10:30:00-0500] [INFO] Server started\n", "stderr": "", "exit_code": 0, "success": true}If an API key is set, add it to the header:
curl -H "X-API-Key: your-secret-key" http://127.0.0.1:8000/commandsValidating the registry
Before restarting the server after editing registry files, you can validate them — like caddy validate does for Caddy config.
CLI
python -m app.validateOptionally specify a custom registry directory:
python -m app.validate /path/to/registryOutput:
MCP Server registry validation: /app/registry
✓ log.yaml → log
✓ log_read.yaml → log_read
✗ broken.yaml: mapping values are not allowed here
⚠ noprogram.yaml → noprogram: Executable not found: /usr/bin/nonexistent
4 file(s) checked · 1 error(s) · 1 warning(s)
Registry has errors — fix them before restarting.Exit codes:
0— all files are valid (warnings are acceptable)1— one or more files have errors2— registry directory does not exist
HTTP
curl http://127.0.0.1:8000/validateReturns a JSON report with results for each file, including duplicate name detection and executable existence checks.
Registering a command
Create a file in registry/ (e.g. my_tool.yaml):
name: my_tool
description: Does something useful.
executable: /usr/local/bin/my_tool
# (relative paths like scripts/my_tool.sh are resolved against
# the project root, so they work in any clone or Docker image)
args:
- name: input
type: string
required: true
help: Path to the input file.
- name: --verbose
type: flag
required: false
help: Enable verbose output.
- name: --mode
type: string
required: false
choices: [fast, slow]
help: Execution mode.Argument spec fields
Field | Type | Notes |
| string | Positional placeholder or |
| string |
|
| bool | Default |
| list | Optional allowed-value whitelist. |
| any | Optional default value, auto-applied when the argument is omitted by the caller. |
| string | Human-readable description. |
| string | Optional clean name for a native tool parameter. When set, it becomes the OpenAPI property name (e.g. |
| bool | When |
A flag type means presence-only (no value); the flag name is added to the command line when the argument is truthy.
Conditional commands (requires)
Commands can declare a requires list of environment-variable conditions. If the conditions are not met, the command is loaded but its route is not registered (it won't appear in GET /commands).
requires:
- "MCP_LOG_ENABLED != false"This is used by log and log_read to disappear when logging is disabled via MCP_LOG_ENABLED=false.
Defaults
Any argument may contain a default value. If the caller omits it, the executor injects it automatically — useful for forcing flags that should always be on (e.g. discord.sh -q for quiet mode):
args:
- name: -q
type: flag
default: true
help: Quiet mode — forced on by default.Native routes for registry commands
Each command defined in registry/ is automatically exposed as its own dedicated FastAPI route — POST /{command_name} — with a Pydantic request model generated from the YAML arg specs. This means the platform can read the OpenAPI schema and expose each command as a native tool with correctly typed parameters (strings, enums, flags, defaults).
These dedicated routes are the only way to execute registry commands — there is no generic POST /execute endpoint. Registry files still populate GET /commands and GET /validate, so you can discover and inspect commands, but execution occurs through the typed per-command routes only.
Unknown fields are rejected (extra: forbid) with a 422 response, and missing required arguments also return 422.
The field_name YAML key controls the parameter name shown to the model. When omitted, the arg name is used (with leading dashes stripped).
Если имя команды реестра конфликтует с существующим маршрутом (например, events, issues), выделенный маршрут пропускается с предупреждением, и команда не может быть выполнена по HTTP (она по-прежнему отображается в GET /commands). Переименуйте команду в реестре, чтобы разрешить её выполнение.
Клиентская библиотека
Небольшой синхронный клиент на базе httpx находится в app/client.py. Он повторяет HTTP API, поэтому модель или скрипт может обращаться к каждой зарегистрированной команде как к нативному вызываемому объекту Python.
from app.client import MCPClient
mc = MCPClient("http://127.0.0.1:8000", api_key="your-secret-key")
# Discover available commands
for cmd in mc.list_commands():
print(cmd["name"], "-", cmd["description"])
# Execute a command
result = mc.execute("log", message="Server started")
print(result["stdout"])
# Bind a command to a reusable callable
log = mc.tool("log")
log(message="Deploy complete")Имена флагов, начинающиеся с -, не являются допустимыми идентификаторами Python, поэтому передавайте их через распаковку словаря: **{"-c": "green"}.
Если на сервере задан MCP_API_KEY, передайте клиенту аргумент api_key= — он будет отправляться как X-API-Key в каждом запросе.
Клиент также работает как контекстный менеджер:
with MCPClient() as mc:
mc.execute("log_read", lines="10")Клиент также предоставляет типизированные удобные методы для API календаря, задач и Gitea (list_events, create_task, list_issues и т. д.).
Структура проекта
mcp-server/
├─ app/
│ ├─ __init__.py # package marker, resolves version via importlib.metadata
│ ├─ main.py # FastAPI app factory + conditional router registration
│ ├─ auth.py # API key authentication dependency
│ ├─ models.py # Pydantic schemas (commands, args, validation)
│ ├─ executor.py # validation + subprocess wrapper with timeout
│ ├─ registry.py # YAML/JSON command loader + validate_registry()
│ ├─ validate.py # `python -m app.validate` CLI
│ ├─ client.py # httpx client library (commands + calendar + Gitea API)
│ ├─ registry_routes.py # Auto-generated native routes for registry commands
│ ├─ caldav_models.py # Pydantic models for CalDAV events/tasks
│ ├─ caldav_service.py # CalDAV service (1 editable + N read-only calendars)
│ ├─ caldav_routes.py # FastAPI router for /tasks (CalDAV-specific)
│ ├─ ics_models.py # Pydantic models for ICS feed config
│ ├─ ics_service.py # ICS feed fetcher, parser, cache
│ ├─ ics_routes.py # ICS service singleton management
│ ├─ unified_routes.py # Unified /events, /calendars router across providers
│ ├─ provider_adapters.py # CalDAVProvider, ICSProvider adapters
│ ├─ providers.py # Global provider registry
│ ├─ gitea_models.py # Pydantic models for Gitea resources
│ ├─ gitea_service.py # Gitea API service (issues, PRs, branches, releases)
│ ├─ gitea_routes.py # FastAPI router for /issues, /prs, /branches, etc.
│ ├─ notify_models.py # Pydantic models for notifications
│ ├─ notify_service.py # Discord + Ntfy notify providers
│ ├─ notify_routes.py # FastAPI router for /notify
│ ├─ weather_models.py # Pydantic models for weather config
│ ├─ weather_service.py # Open-Meteo API client
│ ├─ weather_routes.py # FastAPI router for /weather
│ └─ jobs.py # Lightweight background job scheduler
├─ registry/ # command definitions (one file per command)
│ ├─ log.yaml # logging command
│ └─ log_read.yaml # read log tail
├─ scripts/ # helper scripts referenced by registry YAMLs
│ ├─ log.sh # append to log file
│ ├─ log_read.sh # read log tail
│ └─ config.sh.example # template (unused in Docker; for reference)
├─ tests/ # pytest test suite
│ ├─ conftest.py
│ ├─ test_models.py
│ ├─ test_executor.py
│ ├─ test_registry.py
│ ├─ test_api.py
│ ├─ test_client.py
│ ├─ test_auth.py
│ ├─ test_caldav.py
│ ├─ test_ics.py
│ ├─ test_ics_recurrence.py
│ ├─ test_gitea.py
│ ├─ test_notify.py
│ ├─ test_weather.py
│ ├─ test_logging.py
│ ├─ test_jobs.py
│ └─ test_conditional_endpoints.py
├─ Dockerfile # multi-arch base image definition
├─ LICENSE # MIT license
├─ variants/ # variant Dockerfiles (PHP, Node, etc.)
│ ├─ Dockerfile.php
│ └─ Dockerfile.node
├─ docker-compose.yml # easy local run with volumes
├─ .env.example # environment variable template
├─ .dockerignore # excludes venv, secrets, tests, etc.
├─ pyproject.toml # package metadata + pytest/ruff config
└─ requirements.txt # pip dependencies (used by Dockerfile)Конфигурация
Вся конфигурация задаётся через переменные окружения. Полный справочник с комментариями приведён в .env.example. Сервер читает их при запуске и условно регистрирует конечные точки.
Переменная | Функция | Описание |
| Аутентифication | Ключ API для конечных точек (не задан — открытый доступ) |
| Реестр | Пользовательский каталог реестра |
| Логирование | Путь к файлу журнала |
| Логирование | Каталог журнала (внутри — файл |
| Логирование | Уровень логирования (по умолчанию: INFO) |
| Логирование | Установите |
| CalDAV | URL-адрес сервера CalDAV |
| CalDAV | Имя пользователя CalDAV |
| CalDAV | Пароль CalDAV |
| CalDAV | Имя редактируемого календаря (не задано — все только для чтения) |
| CalDAV | Имена календарей только для чтения через запятую |
| ICS | URL-адрес ICS-ленты только для чтения |
| ICS | Отображаемое имя для ICS-ленты |
| ICS | Интервал обновления кэша в секундах (по умолчанию 300) |
| Gitea | URL-адрес сервера Gitea |
| Gitea | Токен API |
| Gitea | Владелец репозитория по умолчанию |
| Gitea | Имя репозитория по умолчанию |
| Gitea | Показывать нишевые конечные точки в схеме OpenAPI |
| Уведомления | URL-адреса вебхуков Discord (по уровню серьёзности) |
| Уведомления | Переопределение отображаемого имени бота |
| Уведомления | Суффикс заголовка для сообщений Discord |
| Уведомления | URL-адрес сервера Ntfy |
| Уведомления | Темы Ntfy (по уровню серьёзности) |
| Уведомления | Токен доступа Ntfy |
| Уведомления | Базовая аутентификация Ntfy |
| Уведомления | Суффикс заголовка для сообщений ntfy |
| Погода |
|
| Сервер | Часовой пояс (по умолчанию UTC) |
Календарь CalDAV
Сервер может подключаться к серверу CalDAV (например, Radicale, Baikal, Nextcloud) для управления событиями и задачами календаря. В архитектуре используется один редактируемый календарь (в котором события и задачи можно создавать, обновлять и удалять) и несколько календарей только для чтения (видимые, но не доступные для записи).
Когда CALDAV_EDITABLE_CALENDAR не задан, все календари доступны только для чтения, и конечные точки создания/обновления/удаления не регистрируются.
Все события и задачи содержат флаг editable и поле calendar_name, поэтому модель видит полное унифицированное представление календаря, но защищена от случайного изменения календарей, которые ей не следует трогать.
Конфигурация
CALDAV_URL=https://caldav.example.com/dav
CALDAV_USERNAME=user
CALDAV_PASSWORD=secret
# Optional: set to make a calendar writable. When unset, all calendars
# are read-only and write endpoints are not registered.
#CALDAV_EDITABLE_CALENDAR=MyCalendar
# Optional: comma-separated list of read-only calendar names to include.
# If empty, all calendars except the editable one are included as read-only.
#CALDAV_READONLY_CALENDARS=Personal,WorkКогда CALDAV_URL не задан, конечные точки календаря не регистрируются.
Возможности
События (VEVENT): список (с фильтрацией по диапазону дат), получение по UID, создание, обновление, удаление — поддерживаются события на целый день и события с указанием времени.
Задачи (VTODO): список, получение по UID, создание, обновление, удаление — с управлением приоритетом, сроком выполнения и статусом.
Восстановление соединения: если сервер CalDAV становится недоступен в середине операции, сервис автоматически сбрасывает соединение и повторяет попытку один раз. Перехватывает
DAVError,ConnectionError,TimeoutErrorиOSError.Кэширование календаря: список календарей запрашивается один раз за соединение и кэшируется, что исключает избыточные обращения к серверу.
Явные UUIDs: создаваемые события и задачи всегда получают UID
uuid4, что гарантирует возможность их обновления или удаления сразу после создания.
Календарь ICS (только чтение)
Сервер может объединять ICS-ленту календаря только для чтения (например, опубликованный календарь Outlook, iCal из Google Calendar) в единую конечную точку /events наряду с событиями CalDAV.
ICS_CALENDAR_URL=https://outlook.office365.com/owa/calendar/.../calendar.ics
ICS_CALENDAR_NAME=Work
ICS_REFRESH_INTERVAL=300 # seconds (default 300, minimum 30)ICS-лента загружается и кэшируется при запуске, а затем периодически обновляется фоновым заданием. Используйте POST /calendars/refresh, чтобы вручную запустить обновление кэша.
Интеграция с Gitea
Сервер может подключаться к экземпляру Gitea для управления репозиториями, issues, запросами на вытягивание, ветками, релизами и CI-действиями. Когда GITEA_URL не задан, конечные точки Gitea не регистрируются.
Конфигурация
GITEA_URL=https://git.example.com
GITEA_TOKEN=your-api-token
GITEA_DEFAULT_OWNER=your-username
GITEA_DEFAULT_REPO=your-repoКонечные точки issues, веток, PR и релизов принимают необязательные query-параметры owner и repo, которые по умолчанию равны настроенным значениям. Конечные точки информации о репозитории, коммитов и сравнений используют параметры пути (/repos/{owner}/{repo}/...).
Уведомления
Сервер может отправлять уведомления через Discord webhooks и/или Ntfy. Несколько провайдеров могут быть активны одновременно — вызов POST /notify направляет сообщение всем настроенным провайдерам.
Вебхуки Discord настраиваются для каждого уровня серьезности (info, notice, critical, emergency). Если уровень не настроен, система переключается на ближайший более низкий настроенный уровень.
Ntfy работает аналогично, с темами для каждого уровня серьезности. Аутентификация поддерживает либо токен-подход, либо базовую аутентификацию.
Логирование
Команды log и log_read предоставляют простую утилиту ведения журнала: запись сообщений с временными метками в файл и их чтение.
# Log a message
curl -X POST http://127.0.0.1:8000/log \
-H 'Content-Type: application/json' \
-d '{"message": "Deploy complete"}'
# Log with a level
curl -X POST http://127.0.0.1:8000/log \
-H 'Content-Type: application/json' \
-d '{"message": "Disk full", "level": "error"}'
# Read the last 20 lines
curl -X POST http://127.0.0.1:8000/log_read \
-H 'Content-Type: application/json' \
-d '{"lines": "20"}'Путь к файлу журнала определяется (в порядке приоритета):
Переменная окружения
MCP_LOG_FILE— полный путь к файлу журнала.Переменная окружения
MCP_LOG_DIR— каталог, внутри которого находится файлmcp.log.По умолчанию:
/tmp/mcp/mcp.log.
Родительские каталоги создаются автоматически, если они не существуют.
Установите MCP_LOG_ENABLED=false, чтобы полностью отключить логирование: команды log и log_read не будут зарегистрированы, и их маршруты не будут существовать.
Docker
Сервер поставляется с multi-arch Dockerfile, готовым для amd64 и arm64.
Сборка
docker build -t digitaladapt/mcp-server:latest .Для мультиархитектурных сборок (требуется buildx):
docker buildx build --platform linux/amd64,linux/arm64 -t digitaladapt/mcp-server:latest .Запуск
docker run -d --name mcp-server -p 8000:8000 \
--env-file .env \
-e MCP_API_KEY="your-secret-key" \
-v ./registry:/app/registry \
digitaladapt/mcp-server:latestИли с помощью docker compose:
docker compose up -dТома
Монтирование | Назначение |
| Определения команд — переопределение или расширение во время выполнения. |
| Местоположение файла журнала по умолчанию (или установите MCP_LOG_FILE). |
Каталог scripts/ (включая log.sh) включается в образ. Секреты никогда не встраиваются в образ — передавайте их через переменные окружения (--env-file .env).
Детали образа
Основа:
python:3.12-slim(multi-arch)Системные зависимости:
curl,jq(для скриптов),tiniРаботает от: пользователь без root-прав
mcp(uid 1000)Точка входа:
tini(корректная обработка сигналов процесса PID 1)
Сборка вариантов (PHP, Node.js и т. д.)
Базовый Dockerfile создан как основа. Вариантные Dockerfile находятся в variants/ и добавляют поверх дополнительные среды выполнения:
Вариант | Dockerfile | Среда выполнения | Примеры команд |
PHP |
| PHP CLI + curl, mbstring, xml |
|
Node.js |
| Node.js 22 LTS + npm |
|
Сборка варианта (из корня репозитория):
# PHP
docker build -f variants/Dockerfile.php -t digitaladapt/mcp-server:php .
# Node.js
docker build -f variants/Dockerfile.node -t digitaladapt/mcp-server:node .Запуск варианта:
docker run -p 8000:8000 \
--env-file .env \
-v ./registry:/app/registry \
digitaladapt/mcp-server:phpСоздание собственного варианта:
# variants/Dockerfile.ruby
FROM digitaladapt/mcp-server:latest
USER root
RUN apt-get update && apt-get install -y --no-install-recommends \
ruby && rm -rf /var/lib/apt/lists/*
USER mcpЗатем добавьте registry/ruby_eval.yaml, указывающий на /usr/bin/ruby.
Тестирование
Проект включает обширный набор тестов pytest, покрывающий модели, исполнитель, реестр, конечные точки API, клиентскую библиотеку, аутентификацию, приложения CalDAV, разбор ICS, интеграцию с Gitea, уведомления, погоду, логирование, фоновые задания и условную регистрацию конечных точек.
# Install dev dependencies
pip install -e ".[dev]"
# Run the full suite
pytest
# Run with verbose output
pytest -v
# Run a single test module
pytest tests/test_executor.pyРегрессия флага по умолчанию (например, флаг с default: true) покрыта тестами test_executor.py::TestValidateAndBuild::test_flag_default_true_*.
Логика тайм-аута и завершения группы процессов в исполнителе тестируется в test_executor.py.
Заметки по безопасности
Выполнение возможно только для команд из
registry/— конечной точки для произвольных команд не существует.Аргументы проверяются (тип, обязательность, допустимые значения) перед запуском подпроцесса, а неизвестные аргументы отклоняются.
Каждая команда имеет жёсткий тайм-аут 30 секунд с безусловным завершением группы процессов.
Аутентификация по API-ключу — установите
MCP_API_KEY, чтобы требовать заголовокX-API-Keyна всех конечных точках, кроме/api/healthи/api/about. Когда ключ не задано, сервер открыт.Сообщения об ошибках проверяются — внутренние детали пишутся в журнал на стороне сервера, но не раскрываются в HTTP-ответах (важно, так как ошибки попадают обратно в контекстное окно модели).
Запускайте сервер от имени ограниченного пользователя; не давайте ему права sudo.
Команды, позволяющие любоваться файловой системой сервера или произвольное выполнение кода, были удалены намеренно — должны регистрироваться только конкретные разрешённые команды.
Создано Lyra — вашим сереброволосым ассистентом в углу. ✨
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Gateway between LLM agents and world data through eight tools and a bundled endpoint catalog.
AI-callable tools for API mocking, testing, monitoring, security, and automation.
Verified, pay-per-use API tools for AI agents through one authenticated connection.
Build, validate, deploy — HTTP APIs, cron jobs, webhooks and MCP tools — from your AI client.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI models to access external services including weather data, file system operations, and SQLite database interactions through a standardized JSON-RPC interface. Features production-ready architecture with security, rate limiting, and comprehensive error handling.225MIT
- AlicenseNot gradedqualityCmaintenanceEnables building agent-ready APIs that expose tools as both HTTP and MCP endpoints from a single server definition, with automatic OpenAPI, discovery docs, and interactive API reference.5Apache 2.0
- AlicenseNot gradedqualityDmaintenanceProvides AI assistants with 28 developer tools across file, git, code analysis, HTTP, and system domains, enabling tasks like file editing, repository management, code analysis, and shell command execution.232MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to execute Python functions and system commands via Streamable HTTP, including bash, Python code execution, file operations, and text searching.2,013MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/digitaladapt/mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server