Skip to content

namyoungpark-2/docs-mcp-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MCP API 문서 자동화 시스템

Django REST Framework ViewSet을 자동으로 분석하여 OpenAPI 3.0 스펙의 API 문서를 생성하는 완전 자동화 시스템입니다.

📋 목차

🎯 프로젝트 개요

목적

  • Django 프로젝트의 ViewSet을 자동으로 탐지하고 분석
  • 실제 serializer 필드를 기반으로 정확한 OpenAPI 3.0 스펙 생성
  • Request/Response 파라미터, 헤더, 바디 정보 완전 자동화
  • Swagger UI를 통한 직관적인 API 문서 제공

핵심 특징

  • 완전 자동화: 수동 설정 없이 ViewSet 자동 탐지
  • 정확한 스키마: 실제 serializer 필드 1:1 반영
  • 125개 엔드포인트: 모든 ViewSet CRUD 작업 지원
  • 실시간 생성: 코드 변경 시 즉시 문서 업데이트
  • JavaScript 호환: Swagger UI 완벽 지원

🏗️ 시스템 아키텍처

┌─────────────────┐    HTTP Request    ┌─────────────────┐
│   MCP Server    │ ──────────────────► │ Python Parser   │
│  (Spring Boot)  │                    │   (FastAPI)     │
│   Port: 8080    │                    │   Port: 8009    │
└─────────────────┘                    └─────────────────┘
         │                                       │
         │                                       │
         ▼                                       ▼
┌─────────────────┐                    ┌─────────────────┐
│   Swagger UI    │                    │ Django Project  │
│  API Docs HTML  │                    │  ViewSet Files  │
│  /api-docs/html │                    │  /shared_repos/ │
└─────────────────┘                    └─────────────────┘

컴포넌트 설명

  1. Python Parser (FastAPI)

    • Django ViewSet 자동 탐지 및 분석
    • OpenAPI 3.0 스펙 생성
    • 실제 serializer 필드 추출
  2. MCP Server (Spring Boot)

    • Swagger UI 제공
    • JSON API 문서 서빙
    • 프록시 역할
  3. Django Project

    • 분석 대상 ViewSet 파일들
    • 실제 serializer 정의

🚀 주요 기능

1. ViewSet 자동 탐지

  • app/ 디렉토리 내 모든 앱 스캔
  • views.py 또는 views/ 폴더 내 파일 분석
  • class \w+ViewSet 패턴 자동 발견

2. Serializer 필드 추출

  • serializer_class 속성 자동 감지
  • 실제 필드 타입, nullable, required 정보 추출
  • 중첩 serializer 지원

3. OpenAPI 3.0 스펙 생성

  • Request 파라미터 (쿼리, 헤더, 바디)
  • Response 스키마 (상태 코드별)
  • 인증 정보 (Authorization 헤더)
  • Pagination, Search, Filtering 지원

4. CRUD 엔드포인트 자동 생성

  • GET /api/v1/{resource}/ - 목록 조회
  • POST /api/v1/{resource}/ - 생성
  • GET /api/v1/{resource}/{id}/ - 상세 조회
  • PUT /api/v1/{resource}/{id}/ - 수정
  • DELETE /api/v1/{resource}/{id}/ - 삭제

🛠️ 기술 스택

Backend

  • Python 3.12.2: 메인 파싱 로직
  • FastAPI: Python Parser 서버
  • Django: 분석 대상 프로젝트
  • Django REST Framework: ViewSet 분석

Frontend

  • Spring Boot: MCP 서버
  • Swagger UI: API 문서 인터페이스
  • Thymeleaf: HTML 템플릿

개발 도구

  • Gradle: Spring Boot 빌드
  • uvicorn: FastAPI 서버
  • watchfiles: 자동 리로드

📁 프로젝트 구조

mcp-docs-server-final/
├── python-parser/                    # Python Parser 서버
│   ├── main.py                      # FastAPI 서버 진입점
│   ├── src/
│   │   ├── application/             # 애플리케이션 레이어
│   │   │   └── use_cases/
│   │   │       └── generate_api_docs_use_case.py
│   │   ├── domain/                  # 도메인 레이어
│   │   │   └── entities/
│   │   │       ├── api_documentation.py
│   │   │       ├── api_endpoint.py
│   │   │       └── api_parameter.py
│   │   ├── infrastructure/          # 인프라 레이어
│   │   │   ├── generators/
│   │   │   │   └── api_documentation_generator.py
│   │   │   └── parsers/
│   │   │       └── python_parser.py
│   │   └── presentation/            # 프레젠테이션 레이어
│   │       └── controllers/
│   │           └── api_docs_controller.py
│   ├── generated_docs/              # 생성된 API 문서
│   │   └── ucms-be_api_docs.json
│   └── requirements.txt
├── shared_repos/                    # 분석 대상 Django 프로젝트
│   └── ucms-be/
│       └── app/
│           ├── account/
│           ├── revenue/
│           ├── content/
│           └── ... (기타 앱들)
├── src/                             # Spring Boot MCP 서버
│   └── main/
│       ├── java/
│       │   └── com/odk/
│       │       └── controller/
│       │           └── ApiDocsController.java
│       └── resources/
│           ├── templates/
│           │   └── swagger-viewer.html
│           └── static/
│               └── openapi/
├── build.gradle                     # Spring Boot 빌드 설정
└── docker-compose.override.yml      # Docker 설정

🔧 로컬 환경 설정

1. Python 환경 설정

# Python 3.12.2 설치 (pyenv 사용)
pyenv install 3.12.2
pyenv local 3.12.2

# 가상환경 생성 및 활성화
cd python-parser
python -m venv venv
source venv/bin/activate  # macOS/Linux
# 또는
venv\Scripts\activate     # Windows

2. Python 의존성 설치

cd python-parser
pip install -r requirements.txt

3. Spring Boot 환경 설정

# Java 17 이상 필요
java -version

# Gradle 빌드
./gradlew build

🚀 실행 방법

1. Python Parser 서버 시작

cd python-parser
python main.py

서버 정보:

  • URL: http://localhost:8009
  • 자동 리로드: 활성화
  • Django 환경: 자동 설정

2. Spring Boot MCP 서버 시작

# 프로젝트 루트에서
./gradlew bootRun

서버 정보:

  • URL: http://localhost:8080
  • Swagger UI: http://localhost:8080/api-docs/html
  • JSON API: http://localhost:8080/api-docs/json

3. API 문서 생성

# Python Parser 서버가 실행 중인 상태에서
curl -X POST "http://localhost:8009/api/v1/docs/generate/ucms-be?base_url=http://localhost:8009&save_to_file=true"

📖 API 사용법

1. API 문서 생성 엔드포인트

POST /api/v1/docs/generate/{project_name}

파라미터:

  • project_name: 프로젝트 이름 (예: ucms-be)
  • base_url: 기본 URL (예: http://localhost:8009)
  • save_to_file: 파일 저장 여부 (true/false)

응답:

{
  "success": true,
  "message": "API documentation generated successfully",
  "data": {
    "endpoints_count": 125,
    "file_path": "generated_docs/ucms-be_api_docs.json"
  }
}

2. 생성된 문서 확인

  • Swagger UI: http://localhost:8080/api-docs/html
  • JSON 파일: http://localhost:8080/api-docs/json
  • 로컬 파일: python-parser/generated_docs/ucms-be_api_docs.json

🔍 구현 상세 내용

1. ViewSet 자동 탐지 로직

def discover_viewsets(django_app_path: str) -> List[Tuple[str, str]]:
    """
    Django 앱 디렉토리에서 ViewSet 클래스 자동 탐지

    Args:
        django_app_path: Django 앱 경로

    Returns:
        List[Tuple[앱명.ViewSet명, URL경로]]
    """
    viewsets = []

    # app/ 디렉토리 내 모든 앱 스캔
    for app_dir in os.listdir(django_app_path):
        app_path = os.path.join(django_app_path, app_dir)

        if os.path.isdir(app_path):
            # views.py 파일 확인
            views_file = os.path.join(app_path, "views.py")
            if os.path.exists(views_file):
                viewsets.extend(extract_viewsets_from_file(views_file, app_dir))

            # views/ 폴더 확인
            views_dir = os.path.join(app_path, "views")
            if os.path.isdir(views_dir):
                for file in os.listdir(views_dir):
                    if file.endswith(".py"):
                        file_path = os.path.join(views_dir, file)
                        viewsets.extend(extract_viewsets_from_file(file_path, f"{app_dir}/views/{file[:-3]}"))

    return viewsets

2. Serializer 필드 추출 로직

def extract_serializer_from_viewset(viewset_class, viewset_name: str) -> Dict[str, Any]:
    """
    ViewSet에서 실제 사용하는 serializer 필드 추출

    Args:
        viewset_class: ViewSet 클래스
        viewset_name: ViewSet 이름

    Returns:
        Dict[str, Any]: 필드 정보 딕셔너리
    """
    try:
        # 1. serializer_class 속성 확인
        if hasattr(viewset_class, 'serializer_class'):
            serializer_class = viewset_class.serializer_class
            return extract_serializer_fields(serializer_class)

        # 2. get_serializer_class 메서드 확인
        if hasattr(viewset_class, 'get_serializer_class'):
            serializer_class = viewset_class.get_serializer_class()
            return extract_serializer_fields(serializer_class)

        # 3. 소스 코드 분석으로 serializer 패턴 찾기
        return extract_serializer_from_source(viewset_class, viewset_name)

    except Exception as e:
        print(f"[문서 자동화] {viewset_name}에서 serializer 필드 추출 실패: {e}")
        return None

3. OpenAPI 스펙 생성 로직

def generate_openapi_for_viewset(
    viewset_name: str,
    file_path: str,
    base_url: str,
    model_name: str = None,
) -> List[ApiEndpoint]:
    """
    ViewSet에서 OpenAPI 엔드포인트 생성

    Args:
        viewset_name: ViewSet 클래스명
        file_path: ViewSet 파일 경로
        base_url: 기본 URL
        model_name: 모델명 (선택사항)

    Returns:
        List[ApiEndpoint]: 생성된 엔드포인트 목록
    """
    # 1. ViewSet 클래스 import
    viewset_class = import_viewset_class(file_path, viewset_name)

    # 2. Serializer 필드 추출
    serializer_fields = extract_serializer_from_viewset(viewset_class, viewset_name)

    # 3. URL 경로 생성
    resource_name = model_name or viewset_name.replace('ViewSet', '').lower()
    base_path = f"/api/v1/{resource_name}/"

    # 4. CRUD 엔드포인트 생성
    endpoints = []

    # GET /api/v1/{resource}/ - 목록 조회
    endpoints.append(ApiEndpoint(
        path=base_path,
        method=HttpMethod.GET,
        summary=f"Get {resource_name} list",
        description=f"Retrieve a list of {resource_name}",
        parameters=generate_list_parameters(),
        responses=generate_list_responses(serializer_fields)
    ))

    # POST /api/v1/{resource}/ - 생성
    endpoints.append(ApiEndpoint(
        path=base_path,
        method=HttpMethod.POST,
        summary=f"Create {resource_name}",
        description=f"Create a new {resource_name}",
        parameters=generate_create_parameters(),
        request_body=generate_request_body(serializer_fields),
        responses=generate_create_responses(serializer_fields)
    ))

    # 기타 CRUD 엔드포인트들...

    return endpoints

🧪 테스트 방법

1. 단위 테스트

cd python-parser
python -m pytest tests/

2. 통합 테스트

# 1. Python Parser 서버 시작
cd python-parser
python main.py

# 2. API 문서 생성 요청
curl -X POST "http://localhost:8009/api/v1/docs/generate/ucms-be?base_url=http://localhost:8009&save_to_file=true"

# 3. 생성된 파일 확인
ls -la generated_docs/
cat generated_docs/ucms-be_api_docs.json | jq '.paths | keys | length'

3. Swagger UI 테스트

# 1. Spring Boot 서버 시작
./gradlew bootRun

# 2. 브라우저에서 확인
open http://localhost:8080/api-docs/html

4. 엔드포인트별 테스트

# Revenue API 테스트
curl -X GET "http://localhost:8080/api-docs/json" | jq '.paths | keys | grep revenue'

# AdminUser API 테스트
curl -X GET "http://localhost:8080/api-docs/json" | jq '.paths | keys | grep adminuser'

📊 생성된 API 문서 예시

1. Revenue API 엔드포인트

{
  "/api/v1/revenues/": {
    "get": {
      "summary": "Get revenues list",
      "description": "Retrieve a list of revenues",
      "tags": ["revenue"],
      "parameters": [
        {
          "name": "Authorization",
          "in": "header",
          "required": true,
          "description": "Bearer token for authentication",
          "schema": { "type": "string" }
        },
        {
          "name": "page",
          "in": "query",
          "required": false,
          "description": "Page number for pagination",
          "schema": { "type": "integer" }
        }
      ],
      "responses": {
        "200": {
          "description": "Successful response",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": { "type": "integer" },
                  "amount": { "type": "number", "format": "decimal" },
                  "currency": { "type": "string" },
                  "created_at": { "type": "string", "format": "date-time" },
                  "updated_at": { "type": "string", "format": "date-time" }
                }
              }
            }
          }
        }
      }
    }
  }
}

2. 생성된 엔드포인트 통계

  • 총 엔드포인트: 125개
  • ViewSet 개수: 25개
  • 주요 ViewSet:
    • Revenue (16개 필드)
    • RevenueShare (16개 필드)
    • AdminUser (8개 필드)
    • UserActionHistory (12개 필드)
    • VideoSource (23개 필드)
    • Series (18개 필드)
    • Content (다양한 필드)
    • 기타 모든 ViewSet

🔧 트러블슈팅

1. Django 환경 설정 문제

문제: DJANGO_SETTINGS_MODULE 미설정

Error: No module named 'django'

해결책:

def setup_django_environment(django_app_path: str):
    """Django 환경 설정"""
    import os
    import sys
    import django

    # Django 설정 모듈 환경변수 설정
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')

    # 프로젝트 및 앱 경로를 Python 경로에 추가
    project_root = os.path.dirname(django_app_path)
    sys.path.insert(0, project_root)
    sys.path.insert(0, django_app_path)

    # Django 설정
    django.setup()

2. ViewSet Import 실패

문제: 상대 import 오류

Error: attempted relative import with no known parent package

해결책:

def import_viewset_class(file_path: str, viewset_name: str):
    """ViewSet 클래스 import"""
    try:
        # 1. 직접 import 시도
        module_name = get_module_name_from_path(file_path)
        module = importlib.import_module(module_name)
        return getattr(module, viewset_name)
    except ImportError:
        # 2. fallback: 파일 파싱
        return parse_viewset_from_file(file_path, viewset_name)

3. Serializer 필드 추출 실패

문제: cached_property 오류

Error: 'cached_property' object has no attribute 'get_fields'

해결책:

def extract_serializer_fields(serializer_class):
    """Serializer 필드 추출"""
    try:
        # Serializer 인스턴스 생성
        serializer = serializer_class()

        # fields 속성에 안전하게 접근
        if hasattr(serializer, 'fields'):
            fields = serializer.fields
            return {name: extract_field_schema(field) for name, field in fields.items()}
    except Exception as e:
        print(f"Serializer 필드 추출 실패: {e}")
        return None

4. JavaScript 호환성 문제

문제: Swagger UI에서 Object.keys() 오류

TypeError: Cannot convert undefined or null to object

해결책:

def to_openapi_dict(self) -> Dict[str, Any]:
    """OpenAPI 3.0 형식으로 변환"""
    endpoint_dict = {
        "summary": endpoint.summary,
        "description": endpoint.description,
        "tags": endpoint.tags,
        "deprecated": endpoint.deprecated,
        "parameters": [...],
    }

    # null 값 제거로 JavaScript 호환성 확보
    if endpoint.request_body is not None:
        endpoint_dict["requestBody"] = endpoint.request_body

    if endpoint.responses is not None:
        endpoint_dict["responses"] = endpoint.responses

    return endpoint_dict

📈 성능 최적화

1. 캐싱 전략

  • ViewSet 클래스 import 결과 캐싱
  • Serializer 필드 추출 결과 캐싱
  • 파일 변경 감지로 부분 업데이트

2. 병렬 처리

  • 여러 ViewSet 동시 분석
  • 파일 I/O 비동기 처리

3. 메모리 최적화

  • 불필요한 객체 생성 방지
  • 가비지 컬렉션 최적화

🔮 향후 개선 계획

1. 기능 확장

  • GraphQL 스키마 생성 지원
  • API 버전 관리
  • 커스텀 필터링/정렬 지원
  • API 테스트 코드 자동 생성

2. 성능 개선

  • Redis 캐싱 도입
  • 배치 처리 최적화
  • 메모리 사용량 모니터링

3. 사용성 개선

  • 웹 인터페이스 추가
  • 실시간 문서 업데이트
  • API 문서 버전 관리

📞 지원 및 문의

프로젝트 관련 문의사항이나 버그 리포트는 이슈를 통해 제출해 주세요.


개발자: AI Assistant
최종 업데이트: 2024년 12월
버전: 1.0.0

About

docs-mcp-server

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published