Skip to main content
Glama

MCP API 서버

FastAPI 및 FastMCP 기반의 Model Context Protocol (MCP) 서버로, YOLOv8 이미지 분석과 PostgreSQL 데이터베이스 통합을 지원합니다.

프로젝트 개요

이 프로젝트는 Claude와 같은 AI 에이전트가 이미지를 분석하고 결과를 데이터베이스에 저장할 수 있도록 MCP 프로토콜을 통해 제공합니다.

주요 기능:

  • YOLOv8 이미지 분석 - nano/small/medium 모델 지원 (빠른 추론)

  • 감지된 객체 자동 처리 - 크롭 및 base64 인코딩

  • PostgreSQL 데이터 저장 - asyncpg 기반 비동기 DB 연결

  • 4-Layer 아키텍처 - Presenter → Service → Core → Utility 레이어 구분

  • MCP 3가지 전송 방식 - StdIO (Claude Desktop), HTTP/JSON-RPC, WebSocket


Related MCP server: Agent Construct

시스템 요구사항

  • Python: 3.13.3 이상

  • 패키지 매니저: uv (설치 가이드)

  • 메모리: 2GB 이상 (YOLOv8 모델 로드용)

  • 데이터베이스: PostgreSQL 12+ (pgvector 확장 필수)


빠른 시작

1단계: 의존성 설치

# 프로젝트 루트에서 실행
uv sync

2단계: 데이터베이스 설정

PostgreSQL 데이터베이스를 생성하고 .env 파일에 접속 정보를 설정합니다:

# .env 파일 생성
cat > .env << EOF
# PostgreSQL 데이터베이스 설정
DB_HOST=localhost
DB_PORT=5432
DB_NAME=mcp_db
DB_USER=postgres
DB_PASSWORD=your_password

# YOLOv8 모델 설정
YOLO_MODEL=yolov8n.pt
YOLO_HOME=./src/mcp_server/models
YOLO_CONF_THRESHOLD=0.5

# MCP 서버 설정
MCP_SERVER_NAME=mcp-api-server
LOG_LEVEL=INFO
EOF

설정 항목 설명:

항목

기본값

설명

DB_HOST

localhost

PostgreSQL 호스트

DB_PORT

5432

PostgreSQL 포트

DB_NAME

mcp_db

데이터베이스명

DB_USER

postgres

DB 사용자명

DB_PASSWORD

-

DB 암호

YOLO_MODEL

yolov8n.pt

YOLOv8 모델 (nano/s/m/l/x)

YOLO_HOME

./src/mcp_server/models

모델 다운로드 디렉토리

YOLO_CONF_THRESHOLD

0.5

감지 신뢰도 임계값 (0~1)

MCP_SERVER_NAME

mcp-api-server

MCP 서버 이름

LOG_LEVEL

INFO

로그 레벨 (DEBUG/INFO/WARNING)

YOLOv8 모델 선택 가이드:

모델

추론시간

메모리

정확도

추천 상황

yolov8n.pt

~3ms

<100MB

낮음

빠른 응답 필요

yolov8s.pt

~10ms

200MB

중간

✅ 권장

yolov8m.pt

~20ms

400MB

높음

정확도 중시

3단계: 서버 실행

MCP StdIO 서버 (Claude Desktop 연결용):

# FastMCP 방식 (권장, 간단함)
uv run python -m mcp_server

# 또는 MCP SDK 방식 (더 많은 기능)
MCP_SERVER_TYPE=sdk uv run python -m mcp_server

FastAPI HTTP/WebSocket 서버 (원격 클라이언트용):

# 개발 모드 (자동 리로드 활성화)
uv run uvicorn src.mcp_server.main:app --reload

# 프로덕션 모드 (4개 워커)
uv run uvicorn src.mcp_server.main:app --workers 4

서버 시작 확인:

  • FastMCP StdIO: 터미널에서 "Starting FastMCP server" 로그 메시지 확인

  • FastAPI HTTP: 브라우저에서 http://localhost:8000/health 접속 → {"status": "ok"}


프로젝트 구조

mcp-api-server/
│
├── .git/                                    # Git 저장소
├── .python-version                          # Python 3.13.3
├── .env.example                             # 환경변수 템플릿
├── .gitignore
│
├── pyproject.toml                           # uv 프로젝트 설정
├── uv.lock                                  # 의존성 잠금 파일
│
├── README.md                                # 이 파일
├── CLAUDE.md                                # 개발 규약
├── NOTION_USAGE_GUIDE.md                    # Notion 작업 문서 규칙
├── ARCHITECTURE.md                          # 아키텍처 설명
│
├── src/
│   └── mcp_server/                          # 메인 패키지
│       ├── __main__.py                      # MCP StdIO 진입점
│       ├── main.py                          # FastAPI HTTP/WS 진입점
│       ├── fastmcp_server.py                # FastMCP 서버 구현
│       ├── server.py                        # MCP 서버 인스턴스 (SDK용)
│       │
│       ├── commons/                         # 공유 유틸리티 (infrastructure)
│       │   ├── config.py                    # Pydantic Settings (환경변수)
│       │   ├── database.py                  # SQLAlchemy AsyncEngine + asyncpg
│       │   ├── logging.py                   # 로깅 설정
│       │   └── exceptions.py                # 커스텀 예외
│       │
│       ├── core/                            # 도메인 모델 (domain layer)
│       │   ├── yolo_model.py                # YOLOv8 lazy loading (스레드 안전)
│       │   └── embedding_client.py          # 외부 API 클라이언트
│       │
│       ├── schemas/                         # 데이터 모델 (Pydantic)
│       │   ├── response.py                  # 응답 모델 (Detection, AnalysisResult, ImageRecordResponse)
│       │   └── img_model.py                 # DB ORM 모델 (ImageRecord)
│       │
│       ├── services/                        # 비즈니스 로직 (service layer)
│       │   ├── image_analyzer_service.py    # YOLOv8 분석 로직
│       │   ├── image_query_service.py       # DB 조회 로직
│       │   └── repository.py                # DB 저장 로직
│       │
│       ├── tools/                           # MCP Tool 구현 (presenter layer)
│       │   ├── __init__.py
│       │   └── image_analysis.py            # analyze_image tool
│       │
│       ├── resources/                       # MCP Resource (선택)
│       │   └── __init__.py
│       │
│       ├── prompts/                         # MCP Prompt (선택)
│       │   └── __init__.py
│       │
│       └── utils/                           # 공유 유틸리티
│           ├── suppress_output.py           # 출력 억제 데코레이터
│           └── image_utils.py               # 이미지 처리 헬퍼
│
├── tests/                                   # 테스트 스위트
│   ├── conftest.py                          # pytest fixtures
│   ├── test_models.py                       # Pydantic 모델 테스트
│   └── test_*.py                            # 기능별 테스트
│
└── examples/ (선택)                         # 클라이언트 예제
    ├── http_client.py                       # HTTP JSON-RPC 클라이언트
    └── websocket_client.py                  # WebSocket 클라이언트

아키텍처 (4 Layers)

┌──────────────────────────────────────────────────────────┐
│ Presenter Layer (MCP Tools)                              │
│  - tools/image_analysis.py                               │
│  - MCP Protocol 변환 (JSON-RPC 2.0)                      │
└──────────────────┬───────────────────────────────────────┘
                   │
┌──────────────────▼───────────────────────────────────────┐
│ Service Layer (비즈니스 로직)                             │
│  - services/image_analyzer_service.py                    │
│  - services/image_query_service.py                       │
│  - @atransactional 데코레이터로 DB 트랜잭션 관리        │
└──────────────────┬───────────────────────────────────────┘
                   │
┌──────────────────▼───────────────────────────────────────┐
│ Core Layer (도메인 모델)                                 │
│  - core/yolo_model.py (double-checked locking)          │
│  - core/embedding_client.py                             │
│  - schemas/img_model.py (SQLAlchemy ORM)                │
└──────────────────┬───────────────────────────────────────┘
                   │
┌──────────────────▼───────────────────────────────────────┐
│ Utility Layer (공유 인프라)                              │
│  - commons/database.py (AsyncEngine + asyncpg)          │
│  - commons/config.py (환경변수)                         │
│  - utils/suppress_output.py (출력 억제)                 │
└──────────────────────────────────────────────────────────┘

의존성 흐름: Presenter → Service → Core → Utility (역방향 금지)


주요 기능 설명

analyze_image MCP Tool

이미지 파일 경로를 입력받아 YOLOv8로 객체를 감지하고 결과를 저장합니다.

입력 파라미터:

파라미터

타입

필수

설명

image_path

string

이미지 파일 절대 경로

conf_threshold

float

감지 임계값 (0~1, 기본: 0.5)

반환 결과 (AnalysisResult):

{
  "image_path": "/path/to/image.jpg",
  "detections": [
    {
      "class_name": "person",
      "confidence": 0.91,
      "bbox": [100.0, 50.0, 200.0, 300.0]
    }
  ],
  "total_objects": 1
}

처리 흐름:

  1. 입력 검증 - 파일 존재 확인

  2. 이미지 전처리 - PIL로 로드, RGB 변환, 1024×1024 리사이징

  3. 객체 감지 - YOLOv8 추론 (asyncio.to_thread 사용)

  4. DB 저장 - ImageRecord 생성 및 PostgreSQL 저장 (@atransactional)

  5. 결과 반환 - Pydantic AnalysisResult 모델

주요 특징:

  • 비동기 처리 - asyncio.to_thread()로 블로킹 작업 분리

  • 자동 리사이징 - 1024×1024으로 일관된 처리 품질 보장

  • 에러 처리 - DB 연결 실패 시 예외 발생, 로그 기록

  • 타입 안정성 - Pydantic 모델로 검증


데이터베이스 구성

PostgreSQL + asyncpg 설정

# PostgreSQL 설치 (Windows)
# https://www.postgresql.org/download/windows/

# 데이터베이스 생성
psql -U postgres -c "CREATE DATABASE mcp_db;"

데이터베이스 테이블 (자동 생성)

서버 첫 실행 시 init_async_db() 함수가 아래 테이블을 자동으로 생성합니다:

CREATE TABLE image_records (
  id SERIAL PRIMARY KEY,
  path VARCHAR NOT NULL UNIQUE,
  category VARCHAR NOT NULL,
  confidence FLOAT NOT NULL,
  description TEXT,
  objects JSONB,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

비동기 데이터베이스 접근

모든 DB 접근은 @atransactional 데코레이터를 사용합니다:

from mcp_server.commons.database import atransactional, AsyncSession
from mcp_server.schemas.response import AnalysisResult

@atransactional
async def save_analysis(result: AnalysisResult, db: AsyncSession):
    """데이터베이스에 분석 결과 저장"""
    from mcp_server.schemas.img_model import ImageRecord
    
    record = ImageRecord(
        path=result.image_path,
        category="detected_object",
        confidence=result.detections[0].confidence if result.detections else 0.0,
    )
    db.add(record)
    # 트랜잭션 자동 커밋 (예외 발생 시 자동 롤백)

특징:

  • asyncpg 기반 - PostgreSQL 비동기 드라이버

  • Lazy initialization - FastMCP 루프에서만 engine 생성

  • 자동 트랜잭션 - 데코레이터로 commit/rollback 자동 관리

  • 세션 주입 - 함수 파라미터에 자동으로 db 제공


API 엔드포인트

헬스 체크 및 서버 정보

# 헬스 체크
GET /health
→ {"status": "ok"}

# 서버 정보
GET /info

MCP HTTP/JSON-RPC (네트워크 기반)

엔드포인트: POST /mcp/messages

import httpx
import asyncio

async def call_tool():
    async with httpx.AsyncClient() as client:
        response = await client.post(
            "http://localhost:8000/mcp/messages",
            json={
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/call",
                "params": {
                    "name": "analyze_image",
                    "arguments": {
                        "image_path": "/absolute/path/to/image.jpg",
                        "conf_threshold": 0.5
                    }
                }
            }
        )
        print(response.json())

asyncio.run(call_tool())

MCP WebSocket 양방향 통신

엔드포인트: WS /mcp/ws

import asyncio
import json
import websockets

async def ws_client():
    async with websockets.connect("ws://localhost:8000/mcp/ws") as ws:
        await ws.send(json.dumps({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "initialize",
            "params": {}
        }))
        response = await ws.recv()
        print(f"Response: {response}")

asyncio.run(ws_client())

MCP StdIO (Claude Desktop)

Claude Desktop 설정:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "mcp-api-server": {
      "command": "uv",
      "args": ["run", "python", "-m", "mcp_server"],
      "cwd": "/absolute/path/to/mcp-api-server"
    }
  }
}

개발 명령어

테스트 실행

# 모든 테스트 실행
uv run pytest

# 상세 출력
uv run pytest -v

# 특정 테스트 실행
uv run pytest tests/test_models.py -v

# 커버리지 리포트
uv run pytest --cov=src

코드 린트 및 포맷팅

# 린트 검사
uv run ruff check .

# 자동 포맷팅
uv run ruff format .

# 린트 + 포맷 함께
uv run ruff check . && uv run ruff format .

타입 검사

# VS Code Pylance strict mode 사용 (IDE에서 설정)
# .vscode/settings.json:
{
  "python.analysis.typeCheckingMode": "strict"
}

트러블슈팅

YOLOv8 모델 자동 다운로드 실패

# 수동 다운로드
uv run python -c "from ultralytics import YOLO; YOLO('yolov8n.pt')"

# 또는 서버 실행 (자동 다운로드)
uv run uvicorn src.mcp_server.main:app

모델 저장 위치: ./src/mcp_server/models/ (.gitignore 제외)

PostgreSQL 연결 오류

# DB 접속 가능 확인
psql -h localhost -U postgres -d mcp_db -c "SELECT 1;"

# 방화벽 설정 확인 (Windows)
# → Defender 방화벽에서 PostgreSQL 포트 5432 허용

asyncpg 루프 바인딩 에러

에러: 'NoneType' object has no attribute 'send'

원인: asyncpg 커넥션이 다른 event loop에 바인딩됨

해결:

  • init_async_db()는 별도 loop에서 실행 (스키마만 초기화)

  • 실제 engine은 FastMCP/FastAPI loop에서 lazy 생성

  • 자세한 설명은 ARCHITECTURE.md 참고

메모리 부족

# 더 작은 모델 사용
echo "YOLO_MODEL=yolov8n.pt" >> .env

# 또는 명령어로 실행
YOLO_MODEL=yolov8s.pt uv run uvicorn src.mcp_server.main:app

개발 규약

모든 개발 규약은 CLAUDE.md에 자세히 기술되어 있습니다.

주요 규약:

  • 언어: Python 3.13.3 이상

  • 타입 힌팅: Pylance strict mode 필수 (모든 함수/파라미터)

  • 코드 스타일: Ruff (line-length: 100)

  • 데이터 모델: Pydantic BaseModel + SQLAlchemy ORM

  • 커밋 메시지: Conventional Commits

  • 테스트: pytest + pytest-asyncio

  • 아키텍처: 4-Layer (Presenter → Service → Core → Utility)


Git 워크플로우

새 기능 추가

git checkout -b feature/기능-이름
# ... 작업 ...
git add .
git commit -m "feat(scope): 기능 설명"
git push -u origin feature/기능-이름

버그 수정

git checkout -b fix/버그-이름
# ... 수정 ...
git commit -m "fix(scope): 버그 설명"
git push -u origin fix/버그-이름

성능 최적화

YOLOv8 모델 선택

모델

추론시간

메모리

정확도

추천

yolov8n.pt

~3ms

<100MB

낮음

빠른 응답

yolov8s.pt

~10ms

200MB

중간

✅ 권장

yolov8m.pt

~20ms

400MB

높음

정확도 중시

yolov8l.pt

~40ms

800MB

매우높음

매우 정확

비동기 배치 처리

from mcp_server.services.image_analyzer_service import ImageAnalyzerService

service = ImageAnalyzerService()

# 여러 이미지를 동시에 분석
results = await service.analyze_images_abatch([
    "/path/to/image1.jpg",
    "/path/to/image2.jpg",
    "/path/to/image3.jpg",
])

라이선스

MIT License


참고 자료

더 자세한 개발 정보는 CLAUDE.md를 참고하세요.

A
license - permissive license
-
quality - not tested
B
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.

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/istanadodan/img_detect_mcp'

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