Skip to main content
Glama

MCP 서버 – 모듈형 명령 제공자(Modular Command Provider)

임의의 터미널 명령과 CalDAV 캘린더, ICS 피드, Gitea 저장소, 알림 제공자를 언어 모델이 재사용할 수 있는 도구로 노출하는 FastAPI 서버입니다. CLI 프로그램은 registry/에 YAML 파일을 넣으면 등록되고, 통합 기능은 환경 변수를 설정하면 활성화됩니다. 모델은 OpenAPI 스키마로 사용 가능한 도구를 발견하고, 타입이 지정된 HTTP 엔드포인트를 통해 호출합니다.

Why

  • 언어 비종속적(Language-agnostic) – 모든 스크립트, 바이너리, 컴파일된 프로그램을 감쌀 수 있습니다.

  • 자기-설명적(Self-describing) – 각 명령은 인자의 JSON 스키마를 포함합니다.

  • 발견 가능(Discoverable)GET /commands로 모든 것을 나열하며, OpenAPI는 /openapi.json에 있습니다.

  • 안전한 실행 – 인자는 명령이 실행되기 전에 스키마에 대해 검증되며, 30초 타임아웃으로 응답 멈춤을 방지합니다.

  • 조건부 등록 – 엔드포인트는 백엔드 서비스가 구성된 경우에만 존재합니다. LLM은 503을 반환할 라우트를 볼 수 없습니다.

  • 선택적 API 키MCP_API_KEY를 설정하면 /api/health/api/about를 제외한 모든 엔드포인트에 인증을 요구합니다.

Related MCP server: Graft

빠른 시작(Quick Start)

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 헤더를 요구합니다. 설정되지 않은 경우 서버는 공개 상태로 실행됩니다(로컬 개발 또는 신뢰할 수 있는 네트워크에 적합).

시작 안전장치: 아무것도 구성되지 않은 경우(캘린더 제공자, Gitea, 알림 제공자, 날씨, 레지스트리 명령이 없는 경우) 서버는 시작을 거부합니다. 최소한 하나의 기능이 활성화되어야 합니다.

아키텍처

서버는 팩토리 패턴(create_app())을 사용하여 시작 시 환경 변수를 검사하고 각 구성된 통합에 대해 라우터를 조건부로 등록합니다. 이는 OpenAPI 스키마에 실제로 동작할 엔드포인트만 포함된다는 것을 의미하며, LLM은 503을 반환할 라우트를 결코 발견하지 못합니다.

제공자 시스템

캘린더 통합(CalDAV 및 ICS)은 공통 프로토콜을 구현하는 제공자로 구현됩니다. 전역 provider_registry가 모든 활성 제공자를 보관합니다. 통합 라우터(unified_routes.py)는 모든 제공자에 걸쳐 /events, /calendars, 그리고 (ICS가 구성된 경우) /calendars/refresh를 노출합니다. 쓰기 작업(이벤트 생성/수정/삭제)은 편집 가능한 제공자가 존재하는 경우에만 등록됩니다(즉 CALDAV_EDITABLE_CALENDAR가 설정된 CalDAV).

백그라운드 작업

경량 작업 스케줄러(jobs.py)는 앱의 수명 기간 동안 주기적으로 백그라운드 작업을 실행합니다. 현재는 ICS 캐시 새로고침에 사용됩니다. 작업 상태는 GET /jobs에서 확인할 수 있습니다.

API

엔드포인트는 구성에 따라 조건부로 등록됩니다. 아래 표는 가능한 모든 엔드포인트를 보여줍니다; 구성된 기능에 해당하는 것만 존재합니다.

핵심(항상 존재)

메서드

경로

설명

GET

/api/health

Liveness 프로브 (인증 불필요)

GET

/api/about

앱 이름 및 버전 (인증 불필요)

GET

/commands

등록된 모든 명령 나열

GET

/commands/{name}

단일 명령의 스키마 조회

GET

/validate

모든 레지스트리 파일 검증(상세 보고서)

GET

/jobs

주기적 백그라운드 작업 상태 나열

POST

/{command}

레지스트리 명령별 전용 라우트 (자동 생성)

캘린더(CalDAV 또는 ICS가 구성된 경우)

메서드

경로

설명

GET

/events

모든 캘린더 제공자의 이벤트 나열

GET

/events/{uid}

UID로 단일 이벤트 조회

GET

/calendars

메타데이터와 함께 접근 가능한 캘린더 나열

POST

/calendars/refresh

ICS 캐시 새로고침(ICS 구성된 경우)

POST

/events

이벤트 생성 (편집 제공자만)

PUT

/events/{uid}

이벤트 수정 (편집 제공자만)

DELETE

/events/{uid}

이벤트 삭제 (편집 제공자만)

CalDAV 할 일(CalDAV 구성된 경우)

메서드

경로

설명

GET

/tasks

캘린더 할 일 나열(VTODO)

GET

/tasks/{uid}

UID로 단일 할 일 조회

POST

/tasks

할 일 생성 (편집 제공자만)

PUT

/tasks/{uid}

할 일 수정 (편집 제공자만)

DELETE

/tasks/{uid}

할 일 삭제 (편집 제공자만)

Gitea(GITEA_URL 설정된 경우)

메서드

경로

설명

GET

/repos/{owner}/{repo}

저장소 정보 조회

GET

/user/repos

접근 가능한 저장소 목록

GET

/repos/{owner}/{repo}/commits

최근 커밋 목록

GET

/repos/{owner}/{repo}/compare

두 ref 비교(추가 도구)

GET

/issues

이슈 목록(기본 저장소 또는 owner/repo)

GET

/issues/{index}

번호로 단일 이슈 조회

POST

/issues

새 이슈 생성

PATCH

/issues/{index}

이슈 수정(예: 닫기)

GET

/issues/{index}/comments

이슈의 댓글 목록

POST

/issues/{index}/comments

이슈에 댓글 작성

GET

/branches

브랜치 목록(기본 저장소 또는 owner/repo)

POST

/branches

새 브랜치 생성

DELETE

/branches/{name}

브랜치 삭제

GET

/prs

풀 리퀘스트 목록

POST

/prs

풀 리퀘스트 생성

GET

/prs/{index}

단일 PR 조회

PATCH

/prs/{index}

PR 수정(예: 닫기)

POST

/prs/{index}/merge

풀 리퀘스트 병합

GET

/prs/{index}/reviews

PR의 리뷰 목록(추가 도구)

POST

/prs/{index}/comments

PR에 댓글 작성

GET

/actions

CI 워크플로우 실행 목록

GET

/commits/{sha}/statuses

CI 상태 확인(추가 도구)

GET

/releases

릴리즈 목록

POST

/releases

릴리즈 생성

GET

/releases/{release_id}

단일 릴리즈 조회

PATCH

/releases/{release_id}

릴리즈 수정

DELETE

/releases/{release_id}

릴리즈 삭제

추가 도구: /repos/.../compare, /prs/{index}/reviews, 그리고 /commits/{sha}/statuses는 기본적으로 토큰 수를 줄이기 위해 OpenAPI 스키마에서 숨겨져 있습니다. 이를 노출하려면 MCP_GITEA_EXTRA_TOOLS=1을설정하세요.

알림(Discord 또는 Ntfy 구성된 경우)

메서드

경로

설명

POST

/notify

구성된 알림 제공자에게 알림 전송

날씨(WEATHER_LOCATION 설정된 경우)

메서드

경로

설명

GET

/weather

현재 기상 조건 및 일기 예보

예시

# 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"}'

응답:

{"stdout": "[2026-01-15T10:30:00-0500] [INFO] Server started\n", "stderr": "", "exit_code": 0, "success": true}

API 키가 설정된 경우 헤더에 포함하세요:

curl -H "X-API-Key: your-secret-key" http://127.0.0.1:8000/commands

레지스트리 검증

레지스트리 파일을 편집한 후 서버를 재시작하기 전에 이를 검증할 수 있습니다 — 마치 caddy validate가 Caddy의 설정을 검증하는 것과 같습니다.

CLI

python -m app.validate

선택적으로 사용자 지정 레지스트리 디렉토리를 전달:

python -m app.validate /path/to/registry

출력:

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.

종료 코드:

  • 0 — 모든 파일 유효(경고는 허용)

  • 1 — 하나 이상의 파일에 오류가 있음

  • 2 — 레지스트리 디렉토리가 존재하지 않음

HTTP

curl http://127.0.0.1:8000/validate

파일별 결과가 담긴 JSON 리포트를 반환하며, 여기에는 중복 이름 감지와 실행 파일 존재 여부 검사가 포함됩니다.

명령 등록하기

registry/에 파일을 생성하세요 (예: 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.

인자 사양 필드

필드

형식

참고사항

name

string

위치 지정 place hol or --flag name.

type

string

string, int, float, bool, or flag.

required

bool

Default false.

choices

list

Optional allowed-value whitelist.

default

any

Optional default value, auto-applied when the arg

is omitted by the caller.

help

string

Human-readable description.

field_name

string

Optional clean name for the native tool parameter.

When set, this becomes the OpenAPI property name

(e.g. title instead of -t). The original

name is still used as the CLI flag.

hidden

bool

When true, the arg is invisible in the tool

surface but always applied with its default

value. Use for flags that must always be passed

but should never be controllable by the model.

flag 타입은 존재 여부만을 의미합니다(값 없음); 인자가 truthy일 때 플래그 이름이 명령줄에 추가됩니다.

조건부 명령 (requires)

명령은 requires 목록 환경 변수 조건을 선언할 수 있습니다. 조건이 충족되지 않으면 명령은 로드되지만 라우트는 등록되지 않습니다(GET /commands에 나타나지 않음).

requires:
  - "MCP_LOG_ENABLED != false"

이것은 loglog_readMCP_LOG_ENABLED=false로 로깅이 비활성화된 경우 사라지게 하는 데 사용됩니다.

기본값

모든 인자는 default 값을 가질 수 있습니다. 호출자가 인자를 생략하면 실행기가 자동으로 기본값을 채웁니다 — 항상 켜져 있어야 하는 플래그를 강제할 때 유용합니다(예: 자동 모드 시 discord.sh -q):

args:
  - name: -q
    type: flag
    default: true
    help: Quiet mode — forced on by default.

레지스트리 명령을 위한 네이티브 라우트

registry/에 정의된 각 명령은 고유한 전용 FastAPI 라우트 — POST /{command_name} — 로 자동 노출되며, YAML 인자 사양에서 생성된 Pydantic 요청 모델을 가집니다. 이는 플랫폼이 OpenAPI 스키마를 읽고 각 명령을 네이티브 도구로 표시할 수 있음을 의미합니다(문자열, 열거형, 플래그, 기본값 등 올바르게 타입이 지정된 매개변수).

이들 전용 라우트는 레지스트리 명령을 실행할 수 있는 유일한 방법입니다. 일반적인 POST /execute 엔드포인트는 없습니다. 레지스트리 파일은 여전히 GET /commandsGET /validate를 제공하여 명령을 검색하고 검사할 수 있지만, 실행은 타입이 지정된 명령별 라우트를 통해서만 이루어집니다.

알 수 없는 필드는 422 응답과 함께 거부됩니다(extra: forbid), 그리고 필수 인자가 누락된 경우에도 422를 반환합니다.

field_name YAML 키는 모델에 표시되는 매개변수 이름을 제어합니다. 생략된 경우(선행 대시가 제거된) 인자 name이 사용됩니다.

If a registry command's name collides with an existing route (e.g. events, issues), the dedited route is downed with a warning and the command cannot be executed over HTTP (it still appears in GET /commands). Rename the command in the registry to enable execution.

Client library

A small synchronous httpx- based client lives in app/client.py. It mirrors the HTTP API so a model or script can treat each registered command as a native Python callable.

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")

Flag names that start with - aren't valid Python identifiers, so complex them via dict unpacking: **{"-c": "green"}.

If the server has MCP_API_KEY set, pass api_key= to the client — it will be sent as X-API-Key on every request.

The client also works as a context manager:

with MCPClient() as mc:
    mc.execute("log_read", lines="10")

The client also offers typed convenience methods for the public, task, and Gitea APIs (list_events, create_task, list_issues, etc.).

프로젝트 구조

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를 나.서버는 상. 시작 시 이들을 읽어 조건부로 endpoint를 등록합니다.

Variable

Feature

Description

MCP_API_KEY

Auth

API key for endpoints (unset = open access)

MCP_REGISTRY_DIR

Registry

사용자 정의 레지스터 디렉터리

MCP_LOG_FILE

로긕

로그 파일 경로

MCP_LOG_DIR

로그

로그 디렉터리 (내부 파일은 mcp.log)

MCP_LOG_LEVEL

로그

로그 레벨 (기본: INFO)

MCP_LOG_ENABLED

Logging

false로 설정하면 로그 명령 비활성화

CALDAV_URL

CalDAV

CalDAV 서버 URL

CALDAV_USERNAME

CalDAV

CalDAV 사용자 이름

CALDAV_PASSWORD

CalDAV

CalDAV 비밀번호

CALDAV_EDITABLE_CALENDAR

CalDAV

편집 가능한 캔린더 이름 (설정 없= all read-only)

CALDAV_READONLY_CALENDARS

CalDAV

콤로 구분자 단, 수정 가능합니다.

ICS_CALENDAR_URL

ICS

읽기 전용 ICS 피드 URL

ICS_CALENDAR_NAMME

ICS

ICS 피드의 표시 이름

ICS_REFRESH_INTERVAL

ICS

캐시 새로고침 간격 (초단) (기본 300)

GITEA_URL

Gitea

Sertevalcenter URL

GITEA_TOKEN

Gitea

API 토큰

GITEA_DEAULT_OWNER

Gitea

기본 저장소 소유자

GITEA_DEFAULT_REPO

Gitea

기본 저장소 이름

MCP_GITEA_EXTRA_TOOLS

Gitea

OpenAPI schema에 특화 endpoint 노출

DISCORD_*_LOOK

Notify

Severity 수준별 Discor d webhook URL

DISCORD_SERVER_NAMME

Notify

표시 이름 override

DISCORD_TITLE_SUFIX

Notify

Discrod 메시지의 제목 접미사

NTFY_URL

Notify

Ntfy 서버 URL

NTFY_*_TOPIC

Notify

SILENT_TOPIC...

NTFY_TOKEN

Notify

Ntfy 접근 토큰

NTFY_USERNAME / NTFY_POST

Notify

Ntfy 기본 인증

NTFY_TITLE_SUFFIX

Notify

ntfy 메시지의 제목 접미사

WEATHER_LOCATION

Weather

"lat,long" weather data location

TZ

Server

Timezone (기본 UTC)

CalDAV Calendar

서버는 CalDAV 서버 (예: Radicale, Baikal, Nextcloudo) 연결하여 캔린더 이벤트와 작업을 관리할 수 있습니다. 디적 설계은 하나의 편집 가능한 캘린더(이벤트와 작업을 생성, 수정, 삭제할 수 있음)과 multiple read-only 캘린더(보이지만 써지지 않음) 로 나뉩니다.

CALDAV_EDITABLE_CALENDAR 설정하지 않고 처리하지 않는 라우트 등록되지 않습니다.

설정

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 not set, calendar endpoints not registered.

Features

  • Events (VEVENT): list (with date-range filtering), get by UID, create, update, delete (all-day, timed events supported).

  • Tasks (VTODO): list, get by UID, create, update, delete — with 우선순위, 마감일, 상태 관리.

  • 연결 복구: CalDAV server unavailable, system automatically reset and retry once. Catch DAVError, ConnectionError, TimeoutError, and OSError.

  • 캘린더 캐싱: each connection로 목록을 캐시하고 서버 왕복를 줄입니다.

  • Explicit UUID: 생성된 이벤트/작업은 항상 uuid4 UID를 갖고, 생성 직후 update/delete 가능.

ICS Calendar (read-only)

서버는 읽기 전용 ICS calendar feed (e.g. Outlook published calendar, Google Calendar iCal)을 유니파이드 /events endpoint에 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 feed는 시작 시에 불러와 캐시되고, 주기적 백그라운드 작업으로 새로고침됩니다. POST /calendars/refresh를 사용하여 수동으로 캐시 새로고침도 가능.

Gitea Integration

Gitea instance에 연결해서 repositories, issues, pull requests, branches, releases, CI actions를 관리할 수 있습니다. GITEA_URL 없으면 Gitea endpoints not registered.

Configuration

GITEA_URL=https://git.example.com
GITEA_TOKEN=your-api-token
GITEA_DEFAULT_OWNER=your-username
GITEA_DEFAULT_REPO=your-repo

Issues/branches/PR/release endpoints는 optional owner/repo query, default는 config 값. Repo info/commits/compare endpoints는 path params (/repos/{owner}/{repo}/...).

Notify

서버는 Discord incoming webhook 및/또는 Ntfy를 통해 notification 발송 가능합니다. Multiple providers can be active 동시에, /notify endpoint가 fan-out합니다.

Discord webhooks are configured per severity level (info, notice, critical, emergency). If level missing, fallback nearest lower level.

Ntfy works similar with topics per severity. Supports token-based 또는 basic auth.

Logging

loglog_read 명령은 간단한 로깅 유틸리티로, timestamped messages를 파일에 append하고 다시 읽습니다.

# 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"}'

로그 파일 경로는 다음 우선순서로 결정됩니다.

  1. MCP_LOG_FILE env var — full path to log file.

  2. MCP_LOG_DIR env var — directory; file is mcp.log.

  3. Default /tmp/mcp/mcp.log.

상위 directories are auto-created.

MCP_LOG_ENABLED=false로 설정하면 로그 명령 자체가 비활성화됩니다.

Docker

서버는 multi-arch support amd64 and arm64 이미지를 빌드.

Build

docker build -t digitaladapt/mcp-server:latest .

Multi-arch build (buildx required):

docker buildx build --platform linux/amd64,linux/arm64 -t digitaladapt/mcp-server:latest .

Run

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

Volumes

Mount

Purpose

/app/registry

Command definitions — override or extend at runtime.

/tmp/mcp

Default log file location (or set MCP_LOG_FILE).

scripts/ directory (incl. log.sh)가 이미지에 포함됩니다. secrets는 env vars로 제공하세요 (--env-file .env).

Image details

  • Base: python:3.12-slim (multi-arch)

  • System deps: curl, jq, tini

  • Runs as: non-root user mcp (uid 1000)

  • Entrypoint: tini (proper PID-1 signal handling)

Building variants (PHP, Node etc.)

Variant Dockerfiles live in variants/:

Variant

Dockerfile

Runtime

Example commands

PHP

variants/Dockerfile.php

PHP CLI + curl, mbstring, xml

php_eval

Node.js

variants/Dockerfile.node

Node.js 22 LTS + npm

node_run

Build a variant (from repo root):

# 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 .

Run a variant:

docker run -p 8000:8000 \
  --env-file .env \
  -v ./registry:/app/registry \
  digitaladapt/mcp-server:php

Creating your own variant:

# 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

Then add registry/ruby_eval.yaml pointing to /usr/bin/uby.

Testing

The project has comprehensive pytest suite covering models, executor, registry, API endpoints, client library, authentication, CalDAV, ICS parsing, Gitea, notify, weather, logging, background jobs, and condition registration.

# 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

The flag-default regression (e.g. default: true) covered by test_executor.py::test_flag_default_true.

The executor timeout and process-roug kill is tested in test_executor.py.

Security notes

  • Only commands in registry/ can be executed.

  • Args are validated (type, required, choices) before subprocess, unknown rejected.

  • 30-second hard timeout and process-group kill on every command.

  • API key authentication — set MCP_API_KEY to require X-API-Key header.

  • Error messages are sanitized — internal details only logged server-side, not exposed.

  • Run the server under limited user, do not grant sudo.

  • Commands that allow filesystem inspection or arbitrary code execucion removed by design; only whitelisted commands are registered.


Built by Lyra — silver-haired assistant in the corner. ✨

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

0Releases (12mo)
Commit activity

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.

View all MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables 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.
    225
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables 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.
    5
    Apache 2.0

View all related MCP servers

Latest Blog Posts

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