Skip to main content
Glama

MCP Server

범용 MCP(Model Context Protocol) 서버입니다. 내부/외부/OpenAPI 기반 API를 MCP Tool로 등록하고, MCP 클라이언트(예: Codex, Claude 등 MCP 지원 클라이언트)에 Streamable HTTP 전송으로 노출합니다. 관리자 Portal, RBAC/세션 인증, OpenAPI Import, 외부 Credential Service 연동을 통한 Credential 주입, 감사 로그를 제공합니다.

문서 기준: 이 README는 저장소의 실제 소스코드(app/, alembic/, pyproject.toml, Dockerfile, docker-compose.yml, Jenkinsfile, .env.example/env.template)를 직접 분석해 작성되었습니다. 코드로 확인되지 않은 내용은 "확인 불가"로 표기합니다.


1. 프로젝트 소개

  • 목적: 이질적인 백엔드 API들(수동 등록 / 내부 핸들러 / OpenAPI 문서 Import)을 하나의 MCP 서버로 통합해, MCP 클라이언트가 표준 프로토콜(tools/list, tools/call)로 도구를 발견·실행할 수 있게 합니다.

  • 해결하는 문제: 도구별로 제각각인 인증/노출/정책을 서버가 중앙에서 관리하고, 위험도·Scope·사용자별 선택·확인(confirmation) 정책과 감사 로그를 일관되게 적용합니다.

  • MCP Server의 역할: 도구 레지스트리 + 정책 게이트 + 실행 오케스트레이터. 업스트림 API로의 HTTP 실행과 감사 로깅을 담당합니다.

  • Credential Service와의 관계: 실제 자격증명(Secret)은 이 서버가 보관하지 않습니다. 외부 Credential Service(HTTP API)를 호출해 호출자 신원을 확인(/api/v1/me)하고, 필요 시 단기 토큰 교환 후 Credential을 reveal 받아 업스트림 요청에 주입합니다. MCP Server는 HashiCorp Vault를 직접 호출하지 않습니다(아래 3·6절 참고).


Related MCP server: OpenAPI MCP Server

2. 주요 기능

실제 구현이 확인된 기능만 기재합니다. 다수 실행·인증 기능은 feature flag로 감싸여 있고 코드 기본값은 보수적으로 off입니다(11절 표 참고).

  • MCP Tool discovery — DB에 등록된 도구를 운영자 노출 정책·사용자별 선택·Scope에 따라 tools/list로 동적 노출 (app/mcp/registry.py, app/mcp/discoverability.py)

  • MCP Tool executiontools/call 시 다단계 정책 게이트 통과 후 업스트림 HTTP 호출 (app/services/execution/service.py, http_dispatcher.py) — 기본 비활성(MCP_TOOL_EXECUTION_ENABLED=false)

  • OpenAPI Import — OpenAPI 문서(URL/파일)를 가져와 도구를 생성/동기화. 신규 도구는 비활성/비노출로 들어와 관리자가 검토 후 활성화 (app/api/v1/openapi_sources.py)

  • 사용자별 Tool 선택 — 사용자가 자신에게 노출할 도구를 선택 (user_tool_settings, app/services/user_tool_service.py)

  • 관리자 Tool/Provider 관리 — 등록·활성화·MCP 노출·Portal 노출·정책 설정·삭제 (app/api/v1/tools.py, providers.py)

  • Scope 및 위험도 정책 — 도구별 required_scopes, RiskLevel, requires_confirmation (app/db/models/policy.py, app/domain/scopes.py)

  • Credential 주입 — REQUEST_HEADER_PASSTHROUGH / Credential Service reveal 주입 (app/services/execution/) — 기본 비활성

  • 감사 로그 — 모든 tools/list/tools/call을 RECEIVED→완료로 기록, Secret 마스킹 (app/db/models/audit.py, app/services/execution/audit.py)

  • 관리자 Portal / 사용자 Portal — 서버사이드 렌더링 HTML(Jinja2) + 세션 인증 (app/admin/, app/web/)


3. 전체 아키텍처

flowchart LR
    Client[MCP Client]
    Server[MCP Server<br/>FastAPI + MCP SDK]
    DB[(PostgreSQL<br/>schema: mcp)]
    Cred[Credential Service<br/>외부 HTTP API]
    Upstream[업스트림 Tool API<br/>HTTP]
    Vault[HashiCorp Vault]

    Client -- "Streamable HTTP /mcp/" --> Server
    Server -- "SQLAlchemy async / asyncpg" --> DB
    Server -- "/me, token/exchange, reveal" --> Cred
    Server -- "도구 실행(HTTP)" --> Upstream
    Cred -. "이 저장소 범위 밖(코드로 확인 불가)" .-> Vault
  • MCP Server는 Credential Service만 호출하며, HashiCorp Vault로의 직접 연결선은 없습니다(코드 전반에서 hvac/VAULT_ADDR/VAULT_TOKEN/hashicorp 사용 0건).

  • Credential Service가 내부적으로 Vault를 쓰는지는 이 저장소 코드로 확인할 수 없어 점선·"확인 불가"로 표기했습니다.

계층(레이어)

  • app/api, app/web, app/admin — HTTP 진입점(REST v1 / 세션 웹 / 관리자 HTML)

  • app/mcp — MCP 전송·서버 핸들러·도구 매핑·발견/정렬

  • app/services — 실행·인증·감사·사용자도구·OpenAPI 등 도메인 서비스

  • app/repositories — DB 접근 계층

  • app/db, alembic — 모델/스키마/마이그레이션

  • app/domain, app/dto, app/core — 열거형·스코프·DTO·설정·로깅·예외


4. 요청 처리 흐름

실제 코드(app/mcp/server.py, app/services/execution/service.py) 기준입니다.

tools/list

MCP 요청 (/mcp/)
→ DB 세션 확인 (없으면 registry_unavailable 오류)
→ (MCP_MCP_CALLER_AUTH_REQUIRED=true일 때) 호출자 인증: API Key 헤더 → Credential Service GET /api/v1/me → status=ACTIVE 확인
→ Principal 생성(McpPrincipal: scopes/roles/email/status)
→ 사용자별 Tool 선택 정책 적용(ADMIN=전체, USER=본인 enable 목록, 매핑 없으면 0개 = fail-closed)
→ 운영자 노출 정책(SQL): provider/tool enabled·미삭제·ACTIVE, tool.mcp_exposed=true, sync_status≠STALE, policy enabled
→ Scope 필터: required_scopes ⊆ caller scopes 인 도구만
→ 입력 스키마 검증 통과분만
→ 페이지네이션(cursor, 상한 MCP_MCP_MAX_DISCOVERABLE_TOOLS) → 목록 반환
  • 인증 실패 시 DENIED 감사 로그 기록 후 오류 반환.

tools/call

MCP 요청 (/mcp/)
→ RECEIVED 감사 로그 기록
→ (필요 시) 호출자 인증
→ 전역 실행 플래그 확인(MCP_TOOL_EXECUTION_ENABLED)
→ 도구 조회(노출명) / 삭제·비활성 확인
→ MCP 노출 게이트(enforce_mcp_exposed)
→ 사용자별 선택 게이트(USER는 본인 enable 도구만)
→ Provider/Policy 게이트
→ 실행 타입 게이트(HTTP만 지원)
→ Scope 인가(required_scopes 검사)
→ 인자 검증(OFF/WARN/STRICT)
→ 확인 게이트(requires_confirmation=true & confirm≠true → TOOL_CONFIRMATION_REQUIRED) *Secret 호출 이전*
→ Credential 주입 판단(NONE / REQUEST_HEADER_PASSTHROUGH / CREDENTIAL_SERVICE_CREDENTIAL_INJECTION)
→ 업스트림 HTTP 실행(HttpToolDispatcher)
→ 결과 Secret 마스킹(fail-closed) → 감사 로그 완료 기록 → 결과 반환
  • 감사 기록은 fail-open(감사 실패가 응답을 막지 않음), 그 외 정책은 대부분 fail-closed.

  • 구분해야 할 개념: 전역 MCP 호출자 인증(누가 호출했나 — Credential Service /me) ≠ 도구별 upstream credential 주입(어떤 도구에 자격증명을 어떻게 붙이나). REQUEST_HEADER_PASSTHROUGH(inbound 헤더 변환)와 CREDENTIAL_SERVICE_CREDENTIAL_INJECTION(reveal 값 QUERY 주입)은 별개입니다.


5. 인증 및 권한 구조

방식

헤더/전송

적용 대상

Credential Service API Key (cs_...)

X-Credential-Service-Api-Key (기본, MCP_CREDENTIAL_SERVICE_API_KEY_HEADER)

MCP 요청(/mcp/)

Bearer(cs_... API Key 또는 CS 발급 JWT)

Authorization: Bearer <token>

REST 관리 API

세션 쿠키 + CSRF

SessionMiddleware 쿠키 + X-CSRF-Token

관리자/사용자 웹 Portal

  • API Key prefix: cs_ (app/api/rest_auth.py). cs_로 시작하면 API Key 경로로 처리.

  • JWT: MCP는 JWT를 발급하지 않고 검증만 합니다. 알고리즘 HS256(대칭키) 전용, 발급자/청중은 MCP_JWT_ISSUER/MCP_JWT_AUDIENCE(기본 credential-service), 시크릿은 MCP_JWT_SECRET(32자 이상 필수). REST 경로는 /me 재확인으로 JWT sub와 일치하는지도 검증.

  • Principal: Credential Service /me 프로필로 생성(McpPrincipal/RestPrincipal) — scopes/roles/email/status 등 보유.

  • Scope(정확히 7개, app/domain/scopes.py): resources:read, credentials:reveal, servers.read, ssh.execute, logs.read, status.read, disk.read. 정확 일치(와일드카드/대소문자 무시 없음).

  • Role(UserRole): USER, ADMIN. REST 관리 API·관리자 페이지는 ADMIN 필요. 마지막 활성 관리자 강등/비활성 및 자기 자신 강등 방지.

  • 상태 검사: MCP는 /me status=ACTIVE, REST/웹은 McpUser.is_activedeleted_at IS NULL.

  • 인증 실패 응답: CS 비활성 → 403, 무효/취소/검증불가(타임아웃·5xx 포함) → 401, JWT 설정 불가 → 503, 미등록/비활성 사용자 → 403, DB 미구성 → 503.

  • Secret 처리 원칙: 원본 자격증명/Authorization/API Key는 로그·감사에 저장하지 않음. 예시 키는 placeholder(cs_<...>)만 사용.

기본값 주의: MCP_MCP_CALLER_AUTH_REQUIRED, MCP_WEB_AUTH_ENABLED, MCP_JWT_ENABLED는 모두 기본 false입니다. 운영에서는 명시적으로 활성화해야 합니다.


6. Credential Service 연동

MCP Server와 Credential Service의 책임 경계:

  • MCP Server: 정책 판단, 도구 실행, 감사. 자격증명 원본을 저장하지 않음.

  • Credential Service(외부): 사용자 신원(/api/v1/me), API Key→단기 JWT 교환(/api/v1/auth/token/exchange), Credential reveal(/api/v1/my/resources/{resource_id}/credentials/reveal).

동작:

  • 신원 확인: GET {base}/api/v1/meAuthorization: ApiKey <cs_...> 또는 Bearer <JWT>.

  • 토큰 교환: 요청의 cs_ API Key → 단기 Exchange JWT(Authorization: ApiKey <cs_...>로 요청). TTL 상한 3600초, 재시도 없음.

  • Credential 주입: CREDENTIAL_SERVICE_CREDENTIAL_INJECTION은 (교환 JWT로) reveal 후 QUERY 파라미터로만 주입. REQUEST_HEADER_PASSTHROUGH는 허용 목록 헤더를 업스트림 허용 헤더로 전달(CR/LF 인젝션 차단).

  • 평문 노출 방지: reveal 호출은 단기 Bearer JWT로만(원본 cs_ 키는 reveal 엔드포인트로 전송하지 않음). reveal 값은 요청 스코프에서 기억되어 외부 반환 경계에서 마스킹(fail-closed).

  • 타임아웃/재시도: connect 5.0s / read 10.0s / token-exchange 10.0s, 응답 상한 256KiB, 재시도 없음.

  • 관련 환경변수: MCP_CREDENTIAL_SERVICE_BASE_URL, MCP_AUTH_BASE_URL(미설정 시 base_url fallback), MCP_CREDENTIAL_SERVICE_API_KEY_HEADER, MCP_CREDENTIAL_SERVICE_TOKEN_EXCHANGE_ENABLED/_PATH, MCP_CREDENTIAL_SERVICE_CREDENTIAL_INJECTION_ENABLED, MCP_MCP_CALLER_AUTH_REQUIRED 등(11절 표 참고).

HashiCorp Vault 직접 연결 없음: 이 저장소 코드는 Vault SDK/주소/토큰을 전혀 사용하지 않습니다. 자격증명 접근은 오직 위 3개 Credential Service HTTP 엔드포인트를 통합니다.


7. 데이터베이스 구조

  • 엔진/ORM: PostgreSQL + SQLAlchemy 2.0 비동기(asyncpg). DB 미구성 시 "bootstrap 모드"로 기동(엔진 없음).

  • 전용 스키마: mcp(MCP_DATABASE_SCHEMA). 모든 테이블이 스키마 한정, search_path도 해당 스키마로 고정(ADR-0004). 스키마명 검증 정규식 ^[a-z][a-z0-9_]{0,62}$, 예약/공용 스키마 거부.

  • 공통 mixin: UUID PK, 소프트 삭제(deleted_at), 타임스탬프. 활성 유니크 제약은 대개 WHERE deleted_at IS NULL 부분 유니크.

핵심 엔티티 관계:

erDiagram
  mcp_providers ||--o{ mcp_tools : "provider_id (RESTRICT)"
  mcp_providers ||--o| mcp_openapi_sources : "provider_id (CASCADE, unique)"
  mcp_tools ||--o| mcp_tool_http_configs : "tool_id (CASCADE, 1:1)"
  mcp_tools ||--o| mcp_tool_policies : "tool_id (CASCADE, 1:1)"
  mcp_users ||--o{ user_tool_settings : "user_id (CASCADE)"
  mcp_tools ||--o{ user_tool_settings : "tool_id (CASCADE)"
  mcp_users ||--o{ mcp_users : "created_by_user_id (SET NULL)"
  mcp_tools ||--o{ mcp_audit_logs : "tool_id (SET NULL)"
  mcp_providers ||--o{ mcp_audit_logs : "provider_id (SET NULL)"

모델

테이블

설명

Provider

mcp_providers

도구 제공자(업스트림). 인증 설정 보유

Tool

mcp_tools

도구. mcp_exposed/portal_exposed/인증 override 등

ToolHttpConfig

mcp_tool_http_configs

도구 HTTP 실행 설정(1:1)

ToolPolicy

mcp_tool_policies

정책(category/risk/required_scopes/requires_confirmation)(1:1)

OpenApiSource

mcp_openapi_sources

Provider의 OpenAPI Import 소스(0..1)

McpUser

mcp_users

로컬 사용자(USER/ADMIN), Argon2id 해시

UserToolSetting

user_tool_settings

사용자별 도구 enable(is_enabled)

AuditLog

mcp_audit_logs

감사 로그(append-only, 스냅샷 보존, 삭제 시 FK는 SET NULL)

  • 감사 로그: RECEIVED 행 생성 후 완료 시 상태/결과 UPDATE. 원본 자격증명/응답 본문은 저장하지 않고 마스킹된 인자·요약만 저장. 보존/TTL 정책은 코드에 없음(확인 불가).

  • 정책 저장: required_scopes(JSONB, 기본 [])는 저장·검증하지만 강제는 실행 서비스 게이트에서 수행. requires_confirmation은 저장만 하며, 대화형 elicitation 프로토콜이 아니라 실행 게이트(confirm 인자)로 적용.


8. 프로젝트 디렉터리 구조

핵심 경로만 표기합니다.

mcp-server/
├─ app/
│  ├─ main.py            # FastAPI 팩토리(create_app), MCP 마운트, 미들웨어/OpenAPI 커스터마이즈
│  ├─ core/              # config(설정), logging(로깅·Secret redact), security, exceptions
│  ├─ api/               # REST 진입점: rest_auth, deps, health, v1/(tools, providers, users, ...)
│  ├─ web/               # 세션 로그인·Portal 라우트·RBAC 가드
│  ├─ admin/             # 관리자 HTML 라우트 + templates/(SSR)
│  ├─ mcp/               # MCP transport(Streamable HTTP)·server 핸들러·registry·tool_mapper·sanitizer
│  ├─ services/          # execution(실행/인증/감사/credential), auth(jwt/principal), user_tool_service, openapi
│  ├─ repositories/      # DB 접근 계층
│  ├─ db/                # base, session, schema, models/(providers/tools/policy/audit/users ...)
│  ├─ domain/            # enums, scopes, provider/credential_binding
│  ├─ dto/               # 요청/응답 DTO
│  └─ scripts/           # seed_initial_users
├─ alembic/              # env.py(스키마 한정 마이그레이션) + versions/(리비전 13개)
├─ tests/                # unit / integration / e2e / fixtures + conftest.py
├─ docs/                 # architecture / operations / decisions(ADR) / TODO.md
├─ scripts/              # ci_check.sh, phase 검증 스크립트, update_kustomize_image_tag.sh
├─ Dockerfile           # 멀티스테이지(python:3.12-slim, uv)
├─ docker-compose.yml   # 로컬 db(postgres:16) + app
├─ Jenkinsfile          # CI(빌드/푸시/배포 repo 갱신) — 값은 예시 placeholder
├─ pyproject.toml       # 의존성/도구 설정(ruff/mypy/pytest)
└─ uv.lock

9. 요구 환경

  • OS: Linux / WSL(개발), 컨테이너는 python:3.12-slim

  • Python: >=3.12 (pyproject.toml)

  • 패키지 매니저: uv(astral), uv.lock 사용

  • PostgreSQL: 실제 DB 기능 사용 시 필요(compose는 postgres:16-alpine)

  • 선택적 외부 서비스: Credential Service(자격증명 연동 사용 시)

  • Docker / Docker Compose: 로컬 실행·빌드 시(선택)

주요 라이브러리: FastAPI, uvicorn, MCP SDK(mcp), SQLAlchemy 2.0(asyncio)+asyncpg, Alembic, pydantic/pydantic-settings, httpx, PyJWT(검증), pwdlib[argon2], itsdangerous, jsonschema, Jinja2.


10. 로컬 실행

명령은 프로젝트 루트에서 실행합니다. 표기 [WSL zsh]는 로컬 셸입니다.

  1. 저장소 Clone

    # [WSL zsh]
    git clone <YOUR_REPO_URL> mcp-server && cd mcp-server
  2. 의존성 설치

    # [WSL zsh]
    uv sync --dev
  3. 환경변수 준비 (템플릿 복사 후 값 채우기; 실제 Secret은 커밋 금지)

    # [WSL zsh]
    cp .env.example .env
  4. DB 준비 (로컬 Postgres 컨테이너)

    # [Docker]
    docker compose up -d db
  5. 마이그레이션 (DB 접속 환경변수 설정 후)

    # [WSL zsh]
    uv run alembic upgrade head
  6. (선택) 초기 사용자 seed — MCP_SEED_* 환경변수 설정 후

    # [WSL zsh]
    uv run python -m app.scripts.seed_initial_users
  7. 서버 실행

    # [WSL zsh]
    uv run uvicorn app.main:app --host 0.0.0.0 --port 8080
  8. health 확인

    # [WSL zsh]
    curl http://127.0.0.1:8080/health
    curl http://127.0.0.1:8080/ready
  9. OpenAPI / MCP 확인

    # [WSL zsh]
    curl http://127.0.0.1:8080/openapi.json   # Swagger UI: http://127.0.0.1:8080/docs
    # MCP 엔드포인트(정규 URL): http://127.0.0.1:8080/mcp/  (Streamable HTTP)

⚠ 현재 소스 상태에서는 아래 18절의 알려진 이슈(Enum 길이)로 인해 애플리케이션 import가 실패합니다. 위 실행 명령들은 코드 정의상 유효하지만, 실제 기동을 위해서는 해당 이슈 해결이 선행되어야 합니다.


11. 환경변수

접두사 MCP_ + 대문자 필드명. 값은 app/core/config.pySettings 기준(실제 코드 우선). 실제 Secret 값은 표기하지 않습니다. "필수"는 미설정 시 해당 기능이 동작하지 않는 값을 의미합니다.

애플리케이션

변수

필수

기본값

설명

민감

MCP_APP_NAME

아니오

mcp-server

서비스명

아니오

MCP_VERSION

아니오

0.1.0

버전

아니오

MCP_ENV

아니오

local

local/dev/prod

아니오

MCP_LOG_LEVEL

아니오

INFO

로그 레벨

아니오

MCP_HOST

아니오

0.0.0.0

bind host

아니오

MCP_PORT

아니오

8080

bind port

아니오

MCP_DATABASE_SCHEMA

아니오

mcp

전용 PG 스키마(검증됨)

아니오

데이터베이스

변수

필수

기본값

설명

민감

MCP_DB_HOST

DB 사용 시

(없음)

PG 호스트

아니오

MCP_DB_PORT

아니오

5432

PG 포트

아니오

MCP_DB_USER

DB 사용 시

(없음)

PG 사용자

아니오

MCP_DB_PASSWORD

DB 사용 시

(없음)

PG 비밀번호

MCP_DB_NAME

DB 사용 시

(없음)

PG DB명

아니오

인증 / JWT / 세션

변수

필수

기본값

설명

민감

MCP_WEB_AUTH_ENABLED

아니오

false

웹/관리자 인증 활성

아니오

MCP_SESSION_SECRET

web_auth 시 필수

(없음)

세션 서명 시크릿

MCP_SESSION_COOKIE_NAME

아니오

mcp_session

세션 쿠키명

아니오

MCP_SESSION_TTL_SECONDS

아니오

3600

세션 TTL

아니오

MCP_COOKIE_SECURE

아니오

false

Secure 쿠키

아니오

MCP_COOKIE_SAMESITE

아니오

lax

SameSite

아니오

MCP_PASSWORD_MIN_LENGTH

아니오

8

비밀번호 최소 길이

아니오

MCP_PASSWORD_MAX_LENGTH

아니오

128

비밀번호 최대 길이

아니오

MCP_JWT_ENABLED

아니오

false

JWT 검증 활성

아니오

MCP_JWT_ALGORITHM

아니오

HS256

HS256만 허용

아니오

MCP_JWT_SECRET

jwt 시 필수

(없음)

JWT 검증 시크릿(≥32자)

MCP_JWT_ISSUER

아니오

credential-service

발급자

아니오

MCP_JWT_AUDIENCE

아니오

credential-service

청중

아니오

MCP

변수

필수

기본값

설명

MCP_MCP_ENABLED

아니오

true

MCP 전송 마운트

MCP_MCP_PATH

아니오

/mcp

마운트 경로(정규 URL /mcp/)

MCP_MCP_MAX_DISCOVERABLE_TOOLS

아니오

500

노출 도구 상한

MCP_MCP_PAGE_SIZE

아니오

100

페이지 크기

MCP_MCP_JSON_RESPONSE

아니오

false

단일 JSON vs SSE

MCP_MCP_DNS_REBINDING_PROTECTION

아니오

false

Host 헤더 보호

MCP_MCP_ALLOWED_HOSTS

아니오

[]

허용 Host(콤마 구분)

MCP_MCP_CALLER_AUTH_REQUIRED

아니오

false

MCP 호출자 인증 요구

Credential Service

변수

필수

기본값

설명

민감

MCP_CREDENTIAL_SERVICE_BASE_URL

연동 시

(없음)

Credential Service base URL

아니오

MCP_AUTH_BASE_URL

아니오

(없음, base_url fallback)

인증(/me·exchange) base URL

아니오

MCP_CREDENTIAL_SERVICE_API_KEY_HEADER

아니오

X-Credential-Service-Api-Key

요청 API Key 헤더명

아니오

MCP_CREDENTIAL_SERVICE_CREDENTIAL_INJECTION_ENABLED

아니오

false

reveal 주입 활성

아니오

MCP_CREDENTIAL_SERVICE_TOKEN_EXCHANGE_ENABLED

아니오

false

토큰 교환 활성

아니오

MCP_CREDENTIAL_SERVICE_TOKEN_EXCHANGE_PATH

아니오

/api/v1/auth/token/exchange

교환 경로

아니오

MCP_CREDENTIAL_SERVICE_PROFILE_PATH

아니오

/api/v1/me

프로필 경로

아니오

MCP_CREDENTIAL_SERVICE_CONNECT_TIMEOUT_SECONDS

아니오

5.0

connect timeout

아니오

MCP_CREDENTIAL_SERVICE_READ_TIMEOUT_SECONDS

아니오

10.0

read timeout

아니오

MCP_CREDENTIAL_SERVICE_TOKEN_EXCHANGE_TIMEOUT_SECONDS

아니오

10.0

교환 timeout

아니오

MCP_CREDENTIAL_SERVICE_MAX_RESPONSE_BYTES

아니오

262144

응답 상한

아니오

MCP_ALLOWED_CREDENTIAL_SERVICE_CREDENTIAL_FIELDS

아니오

api_key,token,refresh_token,client_secret,webhook_secret

reveal 허용 필드

아니오

Tool 정책 / Credential passthrough

변수

기본값

설명

MCP_TOOL_EXECUTION_ENABLED

false

도구 실행 전역 활성

MCP_REQUEST_CREDENTIAL_PASSTHROUGH_ENABLED

false

헤더 passthrough 활성

MCP_ALLOWED_CREDENTIAL_SOURCE_HEADERS

[X-Credential-Service-Api-Key]

소스 헤더 허용목록

MCP_ALLOWED_PASSTHROUGH_TARGET_HEADERS

[Authorization]

대상 헤더 허용목록

MCP_HTTP_EXEC_CONNECT_TIMEOUT_SECONDS

5.0

실행 connect timeout

MCP_HTTP_EXEC_MAX_RESPONSE_BYTES

2097152

실행 응답 상한

감사 로그

변수

기본값

설명

MCP_AUDIT_LOG_ENABLED

true

감사 로그 활성

MCP_AUDIT_MAX_TEXT_LENGTH

2000

텍스트 최대 길이

OpenAPI Import

MCP_OPENAPI_FETCH_CONNECT_TIMEOUT_SECONDS(5.0), MCP_OPENAPI_FETCH_READ_TIMEOUT_SECONDS(15.0), MCP_OPENAPI_MAX_DOCUMENT_BYTES(5242880), MCP_OPENAPI_MAX_UPLOAD_BYTES(5242880), MCP_OPENAPI_MAX_REDIRECTS(3), MCP_OPENAPI_ALLOW_PRIVATE_NETWORKS(false), MCP_OPENAPI_MAX_OPERATIONS(500), MCP_OPENAPI_MAX_REF_DEPTH(20), MCP_OPENAPI_MAX_SCHEMA_DEPTH(30).

개발/테스트 (Settings 클래스 밖, seed 스크립트가 직접 사용)

MCP_SEED_ADMIN_USERNAME, MCP_SEED_ADMIN_PASSWORD(민감), MCP_SEED_USER_USERNAME, MCP_SEED_USER_PASSWORD(민감), MCP_SEED_UPDATE_EXISTING(기본 false).

코드·템플릿 불일치: .env.example/env.template는 위 변수 중 일부(예: 웹 세션 그룹, 일부 Credential Service 세부 변수, MCP_AUTH_BASE_URL, MCP_VERSION, MCP_SEED_*)를 생략합니다. 생략된 변수는 코드 기본값을 따릅니다.


12. 데이터베이스 Migration

  • 도구: Alembic(비동기 엔진). alembic.inisqlalchemy.url은 비워두고 alembic/env.py가 앱 설정에서 주입.

  • 스키마 한정: version_table_schema=mcp, autogenerate가 mcp 스키마만 대상으로 함(다른 서비스 객체 보호). 온라인 실행 시 마이그레이션 전에 스키마를 별도 트랜잭션으로 생성.

  • 리비전 수: alembic/versions/ 13개. 각 리비전에 upgrade()/downgrade() 구현되어 있음(스텁 아님).

# [WSL zsh]  (DB 접속 환경변수 설정 후)
uv run alembic upgrade head              # 최신 스키마 적용
uv run alembic revision --autogenerate -m "메시지"   # 리비전 생성(개발)
  • downgrade: 리비전에 구현되어 있으나 프로젝트 문서/CI에서 운영 downgrade 절차는 규정하지 않음. 운영 적용 시 스키마 격리·별도 트랜잭션 생성 특성을 확인하세요.

  • 컨테이너/CI는 마이그레이션을 자동 실행하지 않습니다(Dockerfile·Jenkins에 alembic 실행 없음).


13. 테스트 및 품질 검사

# [WSL zsh]
uv run pytest                    # 전체 테스트 (testpaths=tests, asyncio_mode=auto)
uv run pytest -m integration     # integration 마커만 (PostgreSQL 필요)
uv run pytest tests/unit/test_config.py   # 특정 파일
uv run ruff check .              # lint
uv run ruff format --check .     # 포맷 검사
uv run ruff format .             # 포맷 적용
uv run mypy app                  # 타입 체크(strict)
bash scripts/ci_check.sh         # 전체 CI 게이트(포맷→lint→mypy→pytest→phase 검증)
  • 커버리지 설정([tool.coverage])은 없음. [project.scripts] 콘솔 진입점 없음.

  • 현재 소스 상태의 실제 실행 결과는 18절 참조(일부 FAIL/BLOCKED).


14. Docker 실행

# [Docker]
docker compose up -d db          # 로컬 Postgres만
docker compose up                # db + app 함께
docker build -t mcp-server:dev . # 이미지 빌드(멀티스테이지)
  • Dockerfile: 멀티스테이지(python:3.12-slim), 비루트 app 사용자, uv sync --frozen --no-dev, EXPOSE 8080, HEALTHCHECK/health 확인, CMDuvicorn app.main:app --host 0.0.0.0 --port 8080. 컨테이너는 마이그레이션을 실행하지 않음.

  • docker-compose.yml: db(postgres:16-alpine, 5432, healthcheck pg_isready, 볼륨 mcp_pgdata), app(Dockerfile 빌드, db healthy 후 기동, MCP_DB_HOST=db, 8080 노출). DB 비밀번호 기본값은 로컬 개발용입니다.


15. Kubernetes 및 배포

  • 이 저장소에는 범용 Kubernetes/Kustomize/Argo CD manifest가 포함되어 있지 않습니다. 실제 배포 manifest는 외부 배포 저장소에 존재하는 것으로 참조만 됩니다.

  • 포함된 것: Jenkinsfile(빌드→레지스트리 푸시→배포 repo의 이미지 태그 갱신), scripts/update_kustomize_image_tag.sh(kustomization의 newTag 한 줄만 안전 치환).

  • 주의: Jenkinsfile의 레지스트리/배포 repo/자격증명 ID 등은 실제 값이 아닌 예시 placeholder(registry.example.com:8082, github.com/example-org/..., jenkins@example.com 등)입니다. 실제 운영 값으로 교체가 필요합니다.

  • GitHub Actions(.github/) 없음. Redis/메시지 브로커 없음. HashiCorp Vault 직접 연동 없음.


16. API 및 MCP 사용 예시

placeholder만 사용합니다(유효한 실제 키/Secret 아님).

health:

# [WSL zsh]
curl http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/ready

시스템 정보(무인증):

# [WSL zsh]
curl http://127.0.0.1:8080/api/v1/system/info
curl http://127.0.0.1:8080/api/v1/system/mcp

관리 REST API(ADMIN, Bearer):

# [WSL zsh]
curl -H "Authorization: Bearer cs_<YOUR_API_KEY>" http://127.0.0.1:8080/api/v1/tools

MCP 클라이언트 연결(개념 — 실제 클라이언트 설정 형식에 맞게):

transport : Streamable HTTP
url       : http://127.0.0.1:8080/mcp/
header    : X-Credential-Service-Api-Key: cs_<YOUR_API_KEY>   # MCP_MCP_CALLER_AUTH_REQUIRED=true 인 경우
  • tools/list / tools/call은 MCP 클라이언트가 위 엔드포인트로 JSON-RPC를 전송하면 서버가 4절 흐름대로 처리합니다.

  • 관리자 UI: http://127.0.0.1:8080/admin · 사용자 Portal: http://127.0.0.1:8080/portal/tools (웹 인증 활성 시 로그인 필요).


17. 보안 주의사항

  • API Key / JWT Secret: .env에만 두고 저장소에 커밋하지 마세요. MCP_JWT_SECRET은 32자 이상 필수, placeholder 값은 기동 시 거부됩니다.

  • 로그/감사 내 Secret: 로거는 필드명 기반으로 Secret을 마스킹(***REDACTED***)하고, httpx/httpcore 로그를 WARNING으로 낮춰 쿼리스트링 유출을 억제합니다. 감사 로그는 원본 자격증명/응답 본문을 저장하지 않습니다.

  • Credential injection / reveal: reveal은 단기 Bearer JWT로만 호출하고 원본 API Key를 reveal 엔드포인트로 보내지 않습니다. 반환 경계에서 Secret을 마스킹(fail-closed)합니다.

  • 운영 HTTPS / 쿠키: 운영에서는 MCP_COOKIE_SECURE=true 및 TLS 종단(리버스 프록시)을 사용하세요.

  • MCP 전송 보안: MCP 마운트는 네트워크 계층에서 인증되지 않습니다. 네트워크 ACL/프록시로 보호하고, 외부 노출 시 MCP_MCP_DNS_REBINDING_PROTECTION+MCP_MCP_ALLOWED_HOSTS 설정을 검토하세요.

  • CORS: 저장소 코드에서 별도 CORS 미들웨어 설정은 확인되지 않았습니다(확인 불가). 필요 시 리버스 프록시/게이트웨이에서 통제하세요.

  • DB 자격증명: MCP_DB_PASSWORD는 민감정보입니다. compose 기본 비밀번호는 로컬 전용입니다.

  • HashiCorp Vault 토큰: 이 서버는 Vault 토큰을 사용하지 않습니다(직접 연동 없음).

  • 관리자 기능: 마지막 활성 관리자 보호·자기 강등 방지 등 안전장치가 있으나, MCP_WEB_AUTH_ENABLED=false(기본)에서는 웹 인증이 우회되므로 운영에서 반드시 활성화하세요.

  • 공개 저장소 Secret 관리: 실제 IP/도메인/자격증명을 README·코드·커밋에 포함하지 마세요.


18. 현재 제한 사항

코드 분석과 경량 검증(의존성 설치 후 실제 실행)에서 확인된 사실입니다.

  • [치명적] 애플리케이션 import 실패AuthType의 값 CREDENTIAL_SERVICE_CREDENTIAL_INJECTION(39자)이 DB 컬럼 정의 SAEnum(..., length=32)보다 길어 SQLAlchemy가 ValueError: length must be larger or equal than the length of the longest enum value. 32 < 39를 발생시킵니다. app/db/models/provider.py·policy.py·tool.pylength=32 컬럼들이 영향받으며, 이로 인해 앱 import·OpenAPI 생성·pytest 수집이 모두 실패합니다.

  • [타입/정의 충돌] app/services/execution/credential_service.py에서 CredentialResolver 이름이 중복 정의(Protocol vs 구현 클래스)되어 mypyno-redef/Cannot instantiate protocol을 보고합니다.

  • [품질 검사 드리프트] ruff check(E501 라인 길이 등)·ruff format --check(다수 파일 포맷 차이)·mypy가 현재 통과하지 않습니다.

  • 문서·코드 주석 불일치: app/mcp/의 일부 주석은 "tools/call 미구현(Phase 5)"이라고 되어 있으나, 실제 코드는 플래그 활성 시 업스트림 HTTP 실행·Credential 주입을 수행합니다.

  • 로깅 표기: 로깅 모듈 docstring은 "구조적(structured)"이라 하지만 실제는 stdout 평문 포맷입니다.

  • 감사 로그 보존 정책 없음(append-only, TTL/파기 미구현).

  • 외부 의존 검증 불가: 실제 DB/Credential Service 연결이 필요한 동작은 이 문서 작성 범위에서 검증하지 않았습니다.

위 이슈들은 README 작성 범위(문서만 수정)에서 코드를 변경하지 않았습니다. 별도 수정이 필요합니다.


19. 라이선스

  • 저장소에 별도의 LICENSE 파일은 없습니다.

  • pyproject.toml에는 license = { text = "Proprietary" }로 선언되어 있습니다.

라이선스 정책이 확정되지 않았다면 공개 전에 명시적인 LICENSE 파일 추가를 권장합니다(임의로 라이선스를 지정하지 않았습니다).

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (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 Servers

  • A
    license
    -
    quality
    C
    maintenance
    A generic MCP server that dynamically converts OpenAPI-defined REST APIs into tools for LLMs like Claude. It supports multiple authentication methods and transport protocols, enabling seamless interaction with any OpenAPI-compliant API.
    Last updated
    17
    MIT
  • A
    license
    -
    quality
    A
    maintenance
    Self-hosted MCP proxy and aggregation platform. Register multiple upstream MCP servers and expose them through a single unified endpoint with namespace routing, multi-transport support (HTTP/SSE, stdio, OpenAPI→MCP), per-tool overrides, and a web admin UI.
    Last updated
    16
    MIT

View all related MCP servers

Related MCP Connectors

  • The official MCP Server from Mia-Platform to interact with Mia-Platform Console

  • MCP server for interacting with the Supabase platform

  • MCP server for AI access to SmartBear tools, including BugSnag, Reflect, Swagger, PactFlow, QTM4J.

View all MCP Connectors

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/gwanghun-choi/mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server