MCP 서버 통신에 대한 개념적인 내용을 더 숙지하고 싶으시면 이전 글을 읽어주시면 될거 같습니다. 여기에서는 서버 구축에 집중하여 글을 작성하도록 하겠습니다.

1. 공통 환경 구축

1. 프로젝트 생성 및 설정 방법

# 프로젝트를 위한 새 file 생성
uv init

# 가상 환경 생성 및 활성화
uv venv
source .venv/bin/activate

# 의존성 설치
uv add "mcp[cli]" httpx

2. DockerFile 생성

# Python 3.13.5 기반 이미지 사용
FROM python:3.13.5-slim

# 작업 디렉토리 설정
WORKDIR /app

# 프로젝트 파일 복사
COPY main.py .
COPY pyproject.toml .
COPY uv.lock .

# uv 설치
RUN pip install uv

# 의존성 설치
RUN uv sync

# 서버 실행
CMD ["uv", "run", "python3", "main.py"]

Python 버전을 3.10 이상으로 환경 구성하지 않으면 위와 같은 오류가 발생합니다.

Local 로 환경 셋팅을 할 수도 있지만, 그러면 개발자간의 일관적인 개발환경에서 개발하기 어렵기 때문에 도커 기준으로 설명하겠습니다.

2. Stdio 구축

1. main.py

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("mcp_project")

@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b

if __name__ == "__main__":
    import sys
    print("Starting MCP server...", file=sys.stderr)
    mcp.run()
    print("Server stopped", file=sys.stderr)

위와 같이 mcp.run() 을 하면 기본적으로 Stdio 로 동작하게 됩니다. mcp.run(transport='stdio') 로 명시적으로 구현 할 수도 있습니다. 잘 구축이 되었는지 테스트는 Claude Desktop 에서 구현 tool 의 기능을 확인하거나 MCP Inspector 를 통해서 확인 할 수 있습니다. 각각의 방법에 대해서 Claude Desktop 은 아래 5번으로 가시면 따로 설명이 있습니다.

@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b

@mcp.tool() Annotation 을 통해서 클라이언트가 서버에서 호출 할 tool 을 등록할 수 있습니다.

2. 도커 환경 구성하기

 $ docker build -t mcp_server_stdio .

이후 MCP 서버를 subprocess 로 실행 할 때는 claude_desktop_config.json 에서 도커 명령어를 설정해서 Claude Desktop 에서 실행 하거나, MCP Inspector 에서 도커를 실행하면 됩니다.

3. SSE (Server Sent Event) 구축

1. main.py

import uvicorn
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("mcp_project")

@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b

if __name__ == "__main__":
    print("Starting MCP server...")
    uvicorn.run(mcp.sse_app(), host="0.0.0.0", port=8000, log_level="info")

uvicorn.run(mcp.sse_app(), host="0.0.0.0", port=8000, log_level="info") 하면 sse 로 서버를 구축할 수 있습니다. 내부에 다양한 함수들이 있어서 위 방법 말고도 다른 방법으로도 구축할 수 있지만, 여기서는 기본만 다루겠습니다.

host="0.0.0.0" 으로 해서 외부 프로그램 및 브라우저에서 접근 가능하게 합니다.

2. 도커 환경 구성하기

 $ docker build -t mcp_server_sse .

도커 이미지를 빌드 합니다.

 $ docker run -it -p 8000:8000 mcp_server_sse

빌드한 도커 이미지를 실행합니다. 이후 Claude Desktop 에서 Json 포멧을 mcp-remote 에 맞추어서 SSE 로 통신을 진행하면 됩니다.

4. Streamable HTTP 구축

1. main.py

import uvicorn
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("mcp_project")

@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b

if __name__ == "__main__":
    print("Starting MCP server...")
    uvicorn.run(mcp.streamable_http_app(), host="0.0.0.0", port=8000, log_level="info")

uvicorn.run(mcp.streamable_http_app(), host="0.0.0.0", port=8000, log_level="info") 하면 Streamable Http 로 서버를 구축할 수 있습니다. 내부에 다양한 함수들이 있어서 위 방법 말고도 다른 방법으로도 구축할 수 있지만, 여기서는 기본만 다루겠습니다.

host="0.0.0.0" 으로 해서 외부 프로그램 및 브라우저에서 접근 가능하게 합니다.

2. 도커 환경 구성하기

 $ docker build -t mcp_server_http .

도커 이미지를 빌드 합니다.

 $ docker run -it -p 8000:8000 mcp_server_http

빌드한 도커 이미지를 실행합니다. 이후 Claude Desktop 에서 Json 포멧을 mcp-remote 에 맞추어서 Streamable Http 로 통신을 진행하면 됩니다.

5. Claude Desktop과 MCP 서버 연결하기

1. Claude Desktop 다운로드 및 설치 (macOS 또는 Windows)

2. Claude Desktop 구성 파일 설정

구성 편집 버튼을 누르면 claude_desktop_config.json 파일이 있는 디렉토리로 이동을 하게 됩니다. claude_desktop_config.json 에 알맞은 json data 를 넣어주면 Claude Desktop 을 재시작하면 적용되게 됩니다. json 포맷의 경우 아래에 따로 상세히 설명하겠습니다.

3. claude_desktop_config.json

1. Stdio

{
  "mcpServers": {
    "mcp_project": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "mcp_server_stdio:latest"
      ]
    }
  }
}

"command": "docker" 를 통해서 docker 환경에서 실행하는 것을 알 수 있습니다.

2. SSE

{
  "mcpServers": {
    "mcp_project": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://127.0.0.1:8000/sse"
      ]
    }
  }
}
  • npx를 사용하면 mcp-remote 패키지를 사용자의 로컬 환경에 명시적으로 설치하지 않아도 됩니다. npx는 필요한 패키지를 자동으로 다운로드하고 실행합니다. npx는 기본적으로 최신 버전의 패키지를 가져옵니다.
  • mcp-remote는 원격 MCP 서버와 로컬 MCP 클라이언트를 연결해주는 프록시 도구입니다. MCP는 원래 로컬 환경에서 stdio(표준 입출력)를 통해 클라이언트와 서버가 통신하도록 설계되었습니다. 하지만 원격 MCP 서버는 SSE(Server-Sent Events) 또는 HTTP 스트리밍을 사용하므로, 로컬 전용 클라이언트가 이를 직접 처리할 수 없습니다. mcp-remote는 이 간극을 메워주는 역할을 합니다.

3. Streamable HTTP

{
  "mcpServers": {
    "mcp_project": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://127.0.0.1:8000/mcp"
      ]
    }
  }
}

4. 연결확인

연결이 되어 있는것을 확인할 수 있습니다.

6. reference

https://github.com/modelcontextprotocol
https://modelcontextprotocol.io/introduction
https://thetechnomist.com/p/standardizing-ai-value-the-tech-and

profile
가장 아름다운 정답은 서로의 협업안에 있다.

0개의 댓글