Metadata-Version: 2.3
Name: axmp-openapi-fastmcp-server
Version: 1.0.0
Summary: Add your description here
Author: Kilsoo Kang
Author-email: Kilsoo Kang <kilsoo75@gmail.com>
Requires-Dist: diskcache>=5.6.3
Requires-Dist: fastmcp>=3.0.0
Requires-Dist: pathvalidate>=3.3.1
Requires-Dist: pydantic>=2.12.5
Requires-Dist: pydantic-settings>=2.12.0
Requires-Dist: python-dotenv>=1.2.1
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# AXMP OpenAPI FastMCP Server

[![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
[![FastMCP](https://img.shields.io/badge/FastMCP-3.0.0b1+-green.svg)](https://github.com/jlowin/fastmcp)
[![License](https://img.shields.io/badge/license-MIT-lightgrey.svg)](LICENSE)

> **Multiple OpenAPI backends to a single MCP server** — Profile-based configuration with multi-provider OAuth support.

AXMP OpenAPI FastMCP Server는 여러 OpenAPI 호환 백엔드 서비스를 하나의 통합 MCP(Model Context Protocol) 서버로 노출하는 래퍼입니다. [FastMCP](https://github.com/jlowin/fastmcp) 프레임워크를 기반으로 OpenAPI 스펙의 각 operation을 MCP Tool로 자동 변환하며, Keycloak/Google/GitHub/Azure OAuth 인증을 지원합니다.

---

## Table of Contents

- [Architecture](#architecture)
- [Features](#features)
- [Project Structure](#project-structure)
- [Installation](#installation)
- [Configuration](#configuration)
  - [Environment Variables](#environment-variables)
  - [MCP Profile](#mcp-profile)
  - [Backend Auth Config](#backend-auth-config)
- [Usage](#usage)
  - [CLI Mode (HTTP)](#cli-mode-http)
  - [CLI Mode (stdio)](#cli-mode-stdio)
  - [Container Mode](#container-mode)
  - [MCP Host Configuration](#mcp-host-configuration)
- [Authentication](#authentication)
- [Tool Configuration](#tool-configuration)
- [Docker](#docker)
- [Development](#development)
- [CI/CD](#cicd)

---

## Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│                        MCP Host                                 │
│              (Claude Desktop, Cursor, etc.)                     │
└──────────────────────┬──────────────────────────────────────────┘
                       │  MCP Protocol (stdio / HTTP)
                       ▼
┌─────────────────────────────────────────────────────────────────┐
│               AXMP OpenAPI FastMCP Server                       │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │  OAuth Provider (Keycloak / Google / GitHub / Azure)      │  │
│  └───────────────────────────────────────────────────────────┘  │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐            │
│  │  OpenAPI     │  │  OpenAPI     │  │  OpenAPI     │  ...      │
│  │  Provider A  │  │  Provider B  │  │  Provider C  │           │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘            │
│         │                │                │                     │
│  ┌──────┴──────┐  ┌──────┴──────┐  ┌──────┴──────┐            │
│  │ httpx Client│  │ httpx Client│  │ httpx Client│             │
│  │ (API Key)   │  │ (Bearer)    │  │ (Basic)     │             │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘            │
└─────────┼────────────────┼────────────────┼─────────────────────┘
          ▼                ▼                ▼
   ┌──────────┐     ┌──────────┐     ┌──────────┐
   │ Backend  │     │ Backend  │     │ Backend  │
   │ Server A │     │ Server B │     │ Server C │
   └──────────┘     └──────────┘     └──────────┘
```

---

## Features

- **Multi-Backend 통합** — 여러 OpenAPI 백엔드를 하나의 MCP 서버로 통합
- **Profile 기반 설정** — JSON 프로필로 백엔드 구성을 관리
- **Multi-Provider OAuth** — Keycloak, Google, GitHub, Azure 지원
- **Token Forwarding** — 업스트림 OAuth 토큰을 백엔드에 자동 전달
- **유연한 인증** — None / Basic / BearerToken / ApiKey 백엔드별 개별 인증
- **Tool Filtering** — `api_maps` (명시적) / `route_maps` (패턴) 기반 Tool 선택
- **Custom Tool Naming** — 기본 `operationId` 대신 사용자 정의 Tool 이름 지정
- **Tool Description Override** — Tool 설명을 프로필에서 직접 재정의
- **Dual Transport** — `stdio` (로컬) / `http` (원격) 전송 모드
- **Dual Entry Point** — CLI (인자 기반) / Container (환경변수 기반)
- **Multi-Arch Docker** — `linux/amd64`, `linux/arm64` 지원

---

## Project Structure

```
axmp-openapi-fastmcp-server/
├── src/axmp_openapi_fastmcp_server/
│   ├── __init__.py                      # Logging configuration
│   ├── __main__.py                      # python -m entry point
│   ├── settings.py                      # Pydantic Settings (MCP + OAuth)
│   ├── types.py                         # Enums (TransportType, OAuthProvider, AuthHeaderKey)
│   ├── multi_openapi_spec.py            # Multi-backend configuration models
│   ├── openapi_fastmcp_server.py        # Core wrapper (FastMCP + OpenAPI providers)
│   ├── runner/
│   │   ├── cli.py                       # CLI entry point (Click)
│   │   └── container.py                 # Container entry point (env-based)
│   └── auth/providers/
│       └── keycloak.py                  # Keycloak OAuth provider
├── mcp_profiles/                        # MCP profile & OpenAPI spec files
│   ├── mcp_profile_<id>.json            # Backend configuration profiles
│   └── backend_server_<id>.json         # OpenAPI spec files
├── .env                                 # Environment variables
├── Dockerfile                           # Container image definition
├── pyproject.toml                       # Project metadata & dependencies
├── .github/workflows/
│   └── cicd-for-tag.yml                 # CI/CD pipeline (Docker build & push)
└── .pre-commit-config.yaml              # Pre-commit hooks (ruff)
```

---

## Installation

### Requirements

- Python >= 3.12
- [uv](https://docs.astral.sh/uv/) (recommended package manager)

### Install from source

```bash
# Clone repository
git clone <repository-url>
cd axmp-openapi-fastmcp-server

# Install dependencies
uv sync

# Or with pip
pip install -e .
```

### Install from package

```bash
pip install axmp-openapi-fastmcp-server
```

---

## Configuration

### Environment Variables

`.env` 파일 또는 시스템 환경변수로 설정합니다.

#### MCP Server Settings (`AXMP_MCP_` prefix)

| Variable | Description | Default | Required |
|----------|-------------|---------|----------|
| `AXMP_MCP_SERVER_NAME` | MCP 서버 이름 | - | Yes |
| `AXMP_MCP_PORT` | HTTP 리스닝 포트 | `21000` | No |
| `AXMP_MCP_TRANSPORT_TYPE` | 전송 방식 (`http` / `stdio`) | `http` | No |
| `AXMP_MCP_PROFILE_BASE_PATH` | MCP 프로필 디렉토리 경로 | - | Yes |
| `AXMP_MCP_PROFILE_ID` | 사용할 프로필 ID | - | Yes |
| `AXMP_MCP_USE_AUTHORIZATION` | OAuth 인증 활성화 | `False` | No |
| `AXMP_MCP_FORWARD_TOKEN_TO_BACKEND` | 업스트림 토큰을 백엔드에 전달 | `False` | No |

#### OAuth Settings (`AXMP_OAUTH_` prefix)

| Variable | Description | Default | Required |
|----------|-------------|---------|----------|
| `AXMP_OAUTH_PROVIDER` | OAuth 제공자 (`keycloak` / `google` / `github` / `azure`) | `keycloak` | No |
| `AXMP_OAUTH_ISSUER_URL` | OAuth Issuer URL (Keycloak realm URL 등) | - | Yes* |
| `AXMP_OAUTH_CLIENT_ID` | OAuth Client ID | - | Yes* |
| `AXMP_OAUTH_CLIENT_SECRET` | OAuth Client Secret | - | Yes* |
| `AXMP_OAUTH_BASE_URL` | MCP 서버 base URL (callback용) | - | Yes* |
| `AXMP_OAUTH_REQUIRED_SCOPES` | 필요 OAuth 스코프 | `openid,profile,email` | No |
| `AXMP_OAUTH_STORAGE_PATH` | 토큰 저장 경로 | `~/.fastmcp/server/oauth-proxy` | No |

> \* `AXMP_MCP_USE_AUTHORIZATION=True`인 경우 필수

#### Example `.env`

```bash
# MCP Server
AXMP_MCP_SERVER_NAME="axmp-openapi-fastmcp-server"
AXMP_MCP_PORT=8000
AXMP_MCP_TRANSPORT_TYPE="http"
AXMP_MCP_USE_AUTHORIZATION="True"
AXMP_MCP_FORWARD_TOKEN_TO_BACKEND="True"
AXMP_MCP_PROFILE_BASE_PATH="/path/to/mcp_profiles"
AXMP_MCP_PROFILE_ID="1234567890"

# OAuth (Keycloak)
AXMP_OAUTH_PROVIDER="keycloak"
AXMP_OAUTH_ISSUER_URL="https://keycloak.example.com/auth/realms/your-realm"
AXMP_OAUTH_CLIENT_ID="studio-client"
AXMP_OAUTH_CLIENT_SECRET="your-client-secret"
AXMP_OAUTH_BASE_URL="http://127.0.0.1:8000"
AXMP_OAUTH_STORAGE_PATH="/path/to/.fastmcp/server/oauth-proxy"
```

### MCP Profile

MCP 프로필은 백엔드 서버 구성을 정의하는 JSON 파일입니다. 파일 이름은 `mcp_profile_<profile-id>.json` 형식을 따릅니다.

```json
{
  "backends": [
    {
      "server_name": "studio-backend",
      "endpoint": "https://api.example.com",
      "base_path": "/api/v1",
      "timeout": 10,
      "tls_verify": true,
      "spec_file_path": "studio-api.json",
      "auth_config": {
        "type": "ApiKey",
        "api_key_name": "X-Access-Key",
        "api_key_value": "your-api-key"
      },
      "tool_config": {
        "api_maps": [
          {
            "path": "/api/v1/agents",
            "methods": ["get", "post"]
          },
          {
            "path": "/api/v1/agents/{agent_id}",
            "methods": [
              {
                "method": "get",
                "tool_name": "get_agent_by_id",
                "description": "Get agent details by ID"
              }
            ]
          }
        ]
      }
    }
  ]
}
```

#### Backend Configuration Fields

| Field | Type | Description | Required |
|-------|------|-------------|----------|
| `server_name` | `string` | 백엔드 식별 이름 | Yes |
| `endpoint` | `string` | 백엔드 서버 URL | Yes |
| `base_path` | `string` | API base path | No |
| `timeout` | `float` | 요청 타임아웃 (초) | No (`10`) |
| `tls_verify` | `bool` | TLS 인증서 검증 | No (`true`) |
| `spec_file_path` | `string` | OpenAPI spec JSON 파일 (프로필 디렉토리 기준 상대경로) | Yes |
| `auth_config` | `object` | 백엔드 인증 설정 | Yes |
| `tool_config` | `object` | Tool 필터링 및 커스터마이징 설정 | Yes |

### Backend Auth Config

| Auth Type | Fields | Description |
|-----------|--------|-------------|
| `None` | - | 인증 없음 |
| `Basic` | `username`, `password` | HTTP Basic 인증 |
| `BearerToken` | `bearer_token` | Bearer 토큰 인증 |
| `ApiKey` | `api_key_name`, `api_key_value` | 커스텀 헤더 API 키 |

---

## Usage

### CLI Mode (HTTP)

```bash
axmp-openapi-fastmcp-server \
  --port 21000 \
  --transport http \
  --server-name axmp-mixed-openapi-mcp-server \
  --profile-base-path /path/to/mcp_profiles \
  --profile-id 1234567890 \
  --backend-server-auth-configs "studio-backend:X-Access-Key=your-api-key,workspace-backend:X-Access-Key=your-api-key"
```

### CLI Mode (stdio)

```bash
axmp-openapi-fastmcp-server \
  --transport stdio \
  --profile-base-path /path/to/mcp_profiles \
  --profile-id 1234567890 \
  --backend-server-auth-configs "studio-backend:X-Access-Key=your-api-key"
```

#### CLI Options

| Option | Description | Default |
|--------|-------------|---------|
| `--transport` | 전송 방식 (`stdio` / `http` / `sse` / `streamable-http`) | `streamable-http` |
| `--port` | HTTP 리스닝 포트 | `21000` |
| `--server-name` | MCP 서버 이름 | `axmp-openapi-fastmcp-server-<profile-id>` |
| `--profile-base-path` | MCP 프로필 디렉토리 경로 | - (필수) |
| `--profile-id` | 프로필 ID | - (필수) |
| `--backend-server-auth-configs` | 런타임 인증 오버라이드 | - |

#### `--backend-server-auth-configs` Format

프로필의 auth 설정을 런타임에 오버라이드합니다:

```
<server-name>:<key-name>=<value>,<server-name>:<key-name>=<value>
```

- **ApiKey**: `studio-backend:X-Access-Key=zmp-xxxxx`
- **BearerToken**: `studio-backend:bearer_token=eyJhbGci...`
- **Basic**: `studio-backend:username=admin,studio-backend:password=secret`

### Container Mode

환경변수 기반으로 실행됩니다. `.env` 파일 또는 시스템 환경변수를 설정한 후:

```bash
uv run axmp-container-fastmcp-server
```

### MCP Host Configuration

#### Claude Desktop / Cursor

`claude_desktop_config.json` 또는 MCP 호스트 설정에 추가:

```json
{
  "mcpServers": {
    "axmp-openapi-fastmcp-server": {
      "command": "python3",
      "args": [
        "-m",
        "axmp_openapi_fastmcp_server",
        "--transport", "stdio",
        "--profile-base-path", "/path/to/mcp_profiles",
        "--profile-id", "1234567890",
        "--backend-server-auth-configs",
        "studio-backend:X-Access-Key=your-api-key"
      ]
    }
  }
}
```

---

## Authentication

### OAuth Flow (HTTP transport)

`AXMP_MCP_USE_AUTHORIZATION=True`이고 transport가 `http`인 경우 OAuth 인증이 활성화됩니다.

```
MCP Client → MCP Server → OAuth Provider (Keycloak/Google/GitHub/Azure)
                │
                ├─ Token Introspection (검증)
                ├─ User Info Extraction (사용자 정보)
                └─ Scope Validation (스코프 확인)
```

### Token Forwarding

`AXMP_MCP_FORWARD_TOKEN_TO_BACKEND=True`이고 백엔드 auth type이 `BearerToken`인 경우, 업스트림 OAuth 토큰이 자동으로 백엔드 요청에 주입됩니다.

### Supported OAuth Providers

| Provider | Class | Description |
|----------|-------|-------------|
| `keycloak` | `KeyCloakProvider` | Custom implementation with token introspection |
| `google` | `GoogleProvider` | FastMCP built-in |
| `github` | `GitHubProvider` | FastMCP built-in |
| `azure` | `AzureProvider` | FastMCP built-in |

---

## Tool Configuration

### api_maps (Explicit)

특정 경로와 메서드를 명시적으로 MCP Tool로 등록합니다:

```json
{
  "api_maps": [
    {
      "path": "/api/v1/agents",
      "methods": ["get", "post"]
    },
    {
      "path": "/api/v1/agents/{agent_id}",
      "methods": [
        {
          "method": "get",
          "tool_name": "get_agent_detail",
          "description": "Get agent details"
        }
      ]
    }
  ]
}
```

- 문자열 메서드: OpenAPI `operationId`를 Tool 이름으로 사용
- 객체 메서드: `tool_name`과 `description` 커스터마이징 가능
- `api_maps`만 사용 시 명시되지 않은 경로는 자동 제외 (`MCPType.EXCLUDE`)

### route_maps (Pattern)

정규식 패턴으로 Tool을 필터링합니다:

```json
{
  "route_maps": [
    {
      "pattern": "^/api/alert/v1/channels/.*",
      "methods": ["get"],
      "tags": []
    },
    {
      "pattern": "^/api/alert/v1/admin/.*",
      "methods": ["post"],
      "tags": ["alerts"]
    }
  ]
}
```

---

## Docker

### Build

```bash
docker build -t axmp-openapi-fastmcp-server .
```

### Run

```bash
docker run -d \
  --env-file .env \
  -p 8000:8000 \
  -v /path/to/mcp_profiles:/application/mcp_profiles \
  axmp-openapi-fastmcp-server
```

### Dockerfile Overview

```dockerfile
FROM python:3.12.10-slim
WORKDIR /application

# Virtual env + uv install
RUN python -m venv /application/.venv && \
    /application/.venv/bin/pip install uv

# Install dependencies (production only)
COPY . .
RUN /application/.venv/bin/uv sync --no-cache --no-dev

# Container entry point (env-based)
CMD ["/application/.venv/bin/axmp-container-fastmcp-server"]
```

---

## Development

### Setup

```bash
# Install dev dependencies
uv sync

# Install pre-commit hooks
pre-commit install
```

### Linting & Formatting

```bash
# Lint
uv run ruff check .

# Format
uv run ruff format .
```

### Testing

```bash
# Run tests
uv run pytest

# Watch mode
uv run ptw
```

### Pre-commit Hooks

| Hook | Description |
|------|-------------|
| `trailing-whitespace` | 후행 공백 제거 |
| `end-of-file-fixer` | 파일 끝 개행 보장 |
| `debug-statements` | `pdb` import 감지 |
| `ruff` | Lint & auto-fix |
| `ruff-format` | 코드 포맷팅 |

---

## CI/CD

GitHub Actions를 통해 semantic versioning 태그(`v*.*.*`) 푸시 시 자동 빌드 & 배포됩니다.

### Pipeline

```
git tag v1.0.0 → push → GitHub Actions
                           ├─ Checkout
                           ├─ Setup QEMU (multi-arch)
                           ├─ Setup Docker Buildx
                           ├─ Login to Private Registry
                           ├─ Extract metadata (semver tags)
                           └─ Build & Push (linux/amd64, linux/arm64)
```

### Registry

- **Registry**: `zcr.cloudzcp.net`
- **Image**: `zcr.cloudzcp.net/cloudzcp/axmp-openapi-fastmcp-server`
- **Platforms**: `linux/amd64`, `linux/arm64`

---

## Tech Stack

| Category | Technology |
|----------|------------|
| Language | Python 3.12+ |
| MCP Framework | [FastMCP](https://github.com/jlowin/fastmcp) >= 3.0.0b1 |
| Settings | Pydantic Settings |
| HTTP Client | httpx (async) |
| CLI | Click |
| OAuth | Keycloak / Google / GitHub / Azure |
| Encryption | Fernet (cryptography) |
| Build | uv |
| Linting | Ruff |
| Container | Docker (multi-arch) |
| CI/CD | GitHub Actions |

---

## Author

**Kilsoo Kang** — kilsoo75@gmail.com
