mcp-server
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: MCP Tool Server
빠른 시작(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 |
| Liveness 프로브 (인증 불필요) |
GET |
| 앱 이름 및 버전 (인증 불필요) |
GET |
| 등록된 모든 명령 나열 |
GET |
| 단일 명령의 스키마 조회 |
GET |
| 모든 레지스트리 파일 검증(상세 보고서) |
GET |
| 주기적 백그라운드 작업 상태 나열 |
POST |
| 레지스트리 명령별 전용 라우트 (자동 생성) |
캘린더(CalDAV 또는 ICS가 구성된 경우)
메서드 | 경로 | 설명 |
GET |
| 모든 캘린더 제공자의 이벤트 나열 |
GET |
| UID로 단일 이벤트 조회 |
GET |
| 메타데이터와 함께 접근 가능한 캘린더 나열 |
POST |
| ICS 캐시 새로고침(ICS 구성된 경우) |
POST |
| 이벤트 생성 (편집 제공자만) |
PUT |
| 이벤트 수정 (편집 제공자만) |
DELETE |
| 이벤트 삭제 (편집 제공자만) |
CalDAV 할 일(CalDAV 구성된 경우)
메서드 | 경로 | 설명 |
GET |
| 캘린더 할 일 나열(VTODO) |
GET |
| UID로 단일 할 일 조회 |
POST |
| 할 일 생성 (편집 제공자만) |
PUT |
| 할 일 수정 (편집 제공자만) |
DELETE |
| 할 일 삭제 (편집 제공자만) |
Gitea(GITEA_URL 설정된 경우)
메서드 | 경로 | 설명 |
GET |
| 저장소 정보 조회 |
GET |
| 접근 가능한 저장소 목록 |
GET |
| 최근 커밋 목록 |
GET |
| 두 ref 비교(추가 도구) |
GET |
| 이슈 목록(기본 저장소 또는 owner/repo) |
GET |
| 번호로 단일 이슈 조회 |
POST |
| 새 이슈 생성 |
PATCH |
| 이슈 수정(예: 닫기) |
GET |
| 이슈의 댓글 목록 |
POST |
| 이슈에 댓글 작성 |
GET |
| 브랜치 목록(기본 저장소 또는 owner/repo) |
POST |
| 새 브랜치 생성 |
DELETE |
| 브랜치 삭제 |
GET |
| 풀 리퀘스트 목록 |
POST |
| 풀 리퀘스트 생성 |
GET |
| 단일 PR 조회 |
PATCH |
| PR 수정(예: 닫기) |
POST |
| 풀 리퀘스트 병합 |
GET |
| PR의 리뷰 목록(추가 도구) |
POST |
| PR에 댓글 작성 |
GET |
| CI 워크플로우 실행 목록 |
GET |
| CI 상태 확인(추가 도구) |
GET |
| 릴리즈 목록 |
POST |
| 릴리즈 생성 |
GET |
| 단일 릴리즈 조회 |
PATCH |
| 릴리즈 수정 |
DELETE |
| 릴리즈 삭제 |
추가 도구:
/repos/.../compare,/prs/{index}/reviews, 그리고/commits/{sha}/statuses는 기본적으로 토큰 수를 줄이기 위해 OpenAPI 스키마에서 숨겨져 있습니다. 이를 노출하려면MCP_GITEA_EXTRA_TOOLS=1을설정하세요.
알림(Discord 또는 Ntfy 구성된 경우)
메서드 | 경로 | 설명 |
POST |
| 구성된 알림 제공자에게 알림 전송 |
날씨(WEATHER_LOCATION 설정된 경우)
메서드 | 경로 | 설명 |
GET |
| 현재 기상 조건 및 일기 예보 |
예시
# 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.인자 사양 필드
필드 | 형식 | 참고사항 |
| string | 위치 지정 place hol or |
| string |
|
| bool | Default |
| list | Optional allowed-value whitelist. |
| any | Optional default value, auto-applied when the arg |
is omitted by the caller. | ||
| string | Human-readable description. |
| string | Optional clean name for the native tool parameter. |
When set, this becomes the OpenAPI property name | ||
(e.g. | ||
| ||
| bool | When |
surface but always applied with its | ||
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"이것은 log와 log_read가 MCP_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 /commands와 GET /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 |
| Auth | API key for endpoints (unset = open access) |
| Registry | 사용자 정의 레지스터 디렉터리 |
| 로긕 | 로그 파일 경로 |
| 로그 | 로그 디렉터리 (내부 파일은 |
| 로그 | 로그 레벨 (기본: INFO) |
| Logging |
|
| CalDAV | CalDAV 서버 URL |
| CalDAV | CalDAV 사용자 이름 |
| CalDAV | CalDAV 비밀번호 |
| CalDAV | 편집 가능한 캔린더 이름 (설정 없= all read-only) |
| CalDAV | 콤로 구분자 단, 수정 가능합니다. |
| ICS | 읽기 전용 ICS 피드 URL |
| ICS | ICS 피드의 표시 이름 |
| ICS | 캐시 새로고침 간격 (초단) (기본 300) |
| Gitea | Sertevalcenter URL |
| Gitea | API 토큰 |
| Gitea | 기본 저장소 소유자 |
| Gitea | 기본 저장소 이름 |
| Gitea | OpenAPI schema에 특화 |
| Notify | Severity 수준별 Discor d webhook URL |
| Notify | 표시 이름 override |
| Notify | Discrod 메시지의 제목 접미사 |
| Notify | Ntfy 서버 URL |
| Notify | SILENT_TOPIC... |
| Notify | Ntfy 접근 토큰 |
| Notify | Ntfy 기본 인증 |
| Notify | ntfy 메시지의 제목 접미사 |
| Weather | "lat,long" weather data location |
| 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,WorkCALDAV_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, andOSError.캘린더 캐싱: each connection로 목록을 캐시하고 서버 왕복를 줄입니다.
Explicit UUID: 생성된 이벤트/작업은 항상
uuid4UID를 갖고, 생성 직후 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-repoIssues/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
log와 log_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"}'로그 파일 경로는 다음 우선순서로 결정됩니다.
MCP_LOG_FILEenv var — full path to log file.MCP_LOG_DIRenv var — directory; file ismcp.log.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 -dVolumes
Mount | Purpose |
| Command definitions — override or extend at runtime. |
| 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,tiniRuns 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 |
| PHP CLI + curl, mbstring, xml |
|
Node.js |
| Node.js 22 LTS + npm |
|
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:phpCreating 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 mcpThen 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.pyThe 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_KEYto requireX-API-Keyheader.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. ✨
This server cannot be deployed
Maintenance
Related MCP Connectors
Pay-per-call tools for AI assistants: code, data, finance, spreadsheets, media, web, time.
214 tools for AI agents over one MCP endpoint: image, video, audio, 3D, data, storage, mail, GPUs.
AI-callable tools for API mocking, testing, monitoring, security, and automation.
Verified, pay-per-use API tools for AI agents through one authenticated connection.
Related MCP Servers
- 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
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to dynamically discover and call backend tools for arithmetic, SQLite-backed task management, GitHub repository lookups, and text statistics, while also exposing the same functionality through a REST API.-
- AlicenseNot gradedqualityBmaintenanceEnables an AI assistant to invoke local file operations, multi-engine web search, weather, system commands, developer utilities, and code execution over MCP, and includes a web dashboard for managing endpoints, testing tools, and viewing live logs.36 npm1MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to manage workspaces, projects, tasks, and AI agents, and to generate tools from any OpenAPI spec, through a hosted OAuth-secured endpoint or a local stdio package.2,807 npmMIT