Skip to main content
Glama
mcp-demo-server

mcp-demo-server

by mhamzanadeem

MCP 데모 — Python 에이전트 도구를 처음부터 직접 구현하기


MCP란 무엇인가?

MCP (Model Context Protocol) 는 AI 애플리케이션이 하나의 일관된 인터페이스를 통해 외부 도구, 리소스, 프롬프트를 발견하고 사용할 수 있게 해주는 표준화된 프로토콜입니다.

모든 AI 프레임워크가 데이터베이스, API, 파일시스템, 내부 서비스마다 서로 다른 통합 방식을 발명하는 대신, MCP 호스트는 MCP 서버에 연결하여 동일한 프로토콜 표면을 사용할 수 있습니다.

MCP가 해결하는 문제

문제

MCP 솔루션

벤더 종속

통합이 특정 모델 제공자나 에이전트 프레임워크에 묶이지 않고 MCP를 통해 기능을 노출함

비일관적인 도구 호출

도구가 기계가 읽을 수 있는 스키마와 표준화된 발견/호출 의미론을 가짐

컨텍스트 지속성 부재

MCP가 컨텍스트/도구 제공자를 모델과 분리하여 장기 연결을 가능하게 함

동적 데이터 소스

데이터베이스, API, 파일, 내부 시스템이 구현을 모델 런타임에 내장하지 않고 MCP 리소스/도구로 래핑됨

네트워크 상에서 MCP는 JSON-RPC 2.0 메시지를 stdio 및 HTTP 기반 전송(SSE/Streamable HTTP)과 같은 전송 방식을 통해 사용합니다. 이 저장소는 stdio를 사용합니다: 클라이언트가 서버를 하위 프로세스로 실행하고, stdin을 통해 프로토콜 메시지를 보내며, stdout을 통해 응답을 받습니다.


Related MCP server: Weather MCP Server

아키텍처

flowchart TD
    A[User: "What's the weather in London?"] --> B[AI Agent<br/>OpenAI Responses API]
    B --> C[1. Discovers MCP tools]
    B --> D[2. Decides whether to call]
    B --> E[3. Emits function call]
    E --> F[MCP Client<br/>ClientSession + stdio]
    F --> G[initialize]
    F --> H[tools/list]
    F --> I[tools/call]
    I --> J[JSON-RPC 2.0<br/>stdin/stdout]
    J --> K[MCP Server subprocess]
    K --> L[get_current_weather tool]
    K --> M[greeting://{name} resource]

공식 SDK를 사용하는 이유?

이 저장소는 프로토콜을 재구현하는 대신 공식 Python MCP SDK를 사용합니다. SDK는 다음을 제공합니다:

  • 프로토콜 수명주기 및 검증

  • 전송 추상화 (stdio, HTTP/SSE)

  • 타입이 지정된 클라이언트/서버 API

애플리케이션 코드는 여전히 중요한 MCP 개념을 명시적으로 드러냅니다: 서버 등록, 도구 스키마, initialize, tools/list, tools/call, 리소스 읽기, stdio 프로세스 관리.

현재 SDK의 안정적인 v2 API는 서버 구축에 MCPServer를, stdio 클라이언트에 ClientSession/stdio_client를 사용합니다.


프로젝트 구조

mcp-demo/
├── README.md
├── requirements.txt
├── .env.example
├── pyproject.toml
├── src/
│   ├── mcp_server/
│   │   ├── __init__.py
│   │   ├── server.py      # MCP server entry point
│   │   ├── tools.py       # Tool implementations
│   │   ├── handlers.py    # Request handlers
│   │   └── utils.py       # Shared utilities
│   ├── mcp_client/
│   │   ├── __init__.py
│   │   ├── client.py      # MCP client wrapper
│   │   ├── agent.py       # OpenAI agent integration
│   │   └── runner.py      # Demo runner
│   └── shared/
│       ├── __init__.py
│       └── types.py       # Shared Pydantic models
├── tests/
│   ├── test_server.py
│   └── test_client.py
├── examples/
│   └── demo.ipynb
└── scripts/
    └── run_demo.sh

요구 사항

  • Python 3.10 이상

  • OpenAI API 키 (AI 에이전트 데모용)

  • 날씨 API 키 불필요 — 날씨 도구는 결정적 샘플 데이터를 사용하므로 MCP 경로가 오프라인에서도 작동합니다


빠른 시작

1. 가상 환경 생성

python -m venv .venv
source .venv/bin/activate        # Linux/macOS
.venv\Scripts\Activate.ps1       # Windows PowerShell

2. 의존성 설치

python -m pip install --upgrade pip
pip install -r requirements.txt

3. OpenAI 구성

cp .env.example .env

자격 증명으로 .env를 편집하세요:

OPENAI_API_KEY=your_api_key_here
OPENAI_MODEL=gpt-4.1-mini

서버 자체는 OpenAI 키가 필요하지 않습니다.


데모 실행

저장소 루트에서

python src/mcp_client/runner.py

러너가 수행하는 작업:

단계

설명

1️⃣

src/mcp_server/server.py를 하위 프로세스로 실행

2️⃣

MCP 초기화 핸드셰이크 수행

3️⃣

tools/list 호출

4️⃣

발견된 MCP 스키마 → OpenAI 함수 도구로 변환

5️⃣

모델에게 자연어 질문에 답하도록 요청

6️⃣

모델이 get_current_weather를 선택하면 MCP를 통해 tools/call 전송

7️⃣

MCP 결과를 모델에게 다시 전송

8️⃣

최종 답변 출력

9️⃣

서버를 깨끗하게 종료

대안: 셸 래퍼

bash scripts/run_demo.sh

예상 출력

정확한 문구는 모델에 따라 다르지만, 로그 흐름은 다음과 같습니다:

INFO mcp_client.client: -> MCP initialize
INFO mcp_client.client: <- MCP initialize: server=mcp-demo-server
INFO mcp_client.client: -> MCP tools/list
INFO mcp_client.client: <- MCP tools/list: ["get_current_weather"]
INFO mcp_client.agent: User: What's the weather in London?
INFO mcp_client.agent: OpenAI requested tool: get_current_weather {"city":"London","units":"metric"}
INFO mcp_client.client: -> MCP tools/call name=get_current_weather arguments={"city":"London","units":"metric"}
INFO mcp_server.tools: weather lookup city=London units=metric
INFO mcp_client.client: <- MCP tools/call result={"city":"London","temperature":18.0,...}
INFO mcp_client.agent: Final: London is 18°C and partly cloudy.

로그는 의도적으로 애플리케이션 경계에서 MCP 의미 메시지를 보여줍니다. SDK가 JSON-RPC 프레이밍을 내부적으로 처리합니다.


MCP 서버 단독 실행

python src/mcp_server/server.py

stdio MCP 서버는 "멈춘" 것처럼 보입니다 — 이는 정상입니다. stdin에서 프로토콜 메시지를 기다리기 때문입니다. 호스트/클라이언트가 서버를 실행하고 stdio 파이프를 소유해야 합니다.

대화형 프로토콜 검사

pip install "mcp[cli]"
mcp dev src/mcp_server/server.py

시연되는 MCP 메서드

공식 SDK가 JSON-RPC 수명주기를 처리합니다:

메서드

방향

목적

initialize

클라이언트 → 서버

핸드셰이크 및 기능 협상

tools/list

클라이언트 → 서버

사용 가능한 도구 발견

tools/call

클라이언트 → 서버

도구 호출

resources/list

클라이언트 → 서버

사용 가능한 리소스 발견

resources/read

클라이언트 → 서버

리소스 읽기

클라이언트는 기능을 나열하거나 호출하기 전에 명시적으로 initialize()를 호출합니다. 서버의 데코레이터는 Python 타입 어노테이션에서 도구/리소스 스키마를 생성합니다.


도구: get_current_weather

get_current_weather(
    city: str,
    units: Literal["metric", "imperial"] = "metric"
) -> WeatherResponse

구조화된 Pydantic 기반 페이로드를 반환합니다:

{
  "city": "London",
  "temperature": 18.0,
  "units": "metric",
  "condition": "partly cloudy",
  "humidity_percent": 72
}

알 수 없는 도시는 서버를 중단시키는 대신 통제된 MCP 도구 오류로 실패합니다.


에이전트 통합 흐름

에이전트는 데모를 집중적으로 유지하기 위해 일반 OpenAI 함수 호출(추가 프레임워크 없음)을 사용합니다:

flowchart LR
    A[MCP Tool Schema] --> B[OpenAI Function Tool]
    B --> C[Model Chooses Function]
    C --> D[MCP ClientSession.call_tool]
    D --> E[MCP Server Executes Tool]
    E --> F[Function Call Output]
    F --> G[Final Model Answer]

이것은 에이전트 프레임워크가 래핑하는 것과 동일한 패턴입니다: MCP 도구 발견 → 모델에 스키마 노출 → 선택된 호출을 MCP로 다시 라우팅 → 결과를 다음 모델 턴에 공급.


테스트

pytest -q

테스트 스위트가 다루는 범위:

  • ✅ 도구 실행 (미터법 날씨)

  • ✅ 도구 실행 (야드파운드법 날씨)

  • ✅ 검증/오류 동작 (알 수 없는 도시)

  • ✅ 프로세스 내 MCP 클라이언트 발견 및 도구 호출

테스트는 가능한 경우 SDK의 인메모리 클라이언트를 사용합니다 — 실제 MCP 프로토콜 계층을 실행하면서 하위 프로세스 불안정성을 피합니다.


포맷팅 및 린팅

이 프로젝트는 Ruff 를 사용합니다:

# Check
ruff check .
ruff format --check .

# Format
ruff format .

프로덕션 참고 사항

이 데모는 의도적으로 작지만 여러 프로덕션 고려 사항을 나타냅니다:

고려 사항

구현

stdout 규율

서버는 앱 로그를 stdout에 출력하지 않음 (MCP 전용); 로그는 logging을 통해 stderr로 전송

타입이 지정된 I/O

Pydantic 모델이 애플리케이션 경계에서 도구 입력/출력 검증

통제된 실패

도구 예외 → MCP 오류 결과 (SDK), 프로세스 중단이 아님

하위 프로세스 수명주기

SDK의 stdio 컨텍스트 관리자가 프로세스 시작/종료를 소유

최소 권한 환경

MCP stdio 클라이언트가 하위 프로세스에 필요한 환경 변수만 명시적으로 전달

동적 발견

에이전트가 날씨 도구 스키마를 하드코딩하지 않고 tools/list를 통해 발견

실제 외부 데이터 소스의 경우: 결정적 날씨를 인증된 API/데이터베이스 호출로 대체하고, 타임아웃, 재시도, 속도 제한, 관찰 가능성, 비밀 관리를 추가하세요.


프로토콜 개념 모델

단순화된 JSON-RPC 시퀀스:

// Client -> Server
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}

// Server -> Client
{"jsonrpc":"2.0","id":1,"result":{...}}

// Client -> Server
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}

// Server -> Client
{"jsonrpc":"2.0","id":2,"result":{"tools":[...]}}

// Client -> Server
{"jsonrpc":"2.0","id":3,"method":"tools/call",
 "params":{"name":"get_current_weather","arguments":{"city":"London"}}}

// Server -> Client
{"jsonrpc":"2.0","id":3,"result":{"content":[...],"structuredContent":{...}}}

정확한 프로토콜 스키마는 MCP 사양과 SDK가 유지 관리합니다. 위 내용은 교육 목적으로 의도적으로 단순화되었습니다.


참고 자료


Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    Enables AI agents to retrieve real-time weather conditions and forecasts via OpenWeatherMap API. Supports interactive weather queries and travel planning through MCP tools, resources, and prompts.
    2
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides weather data from OpenWeatherMap API through MCP tools and a REST API with OpenAPI support. Enables LLM agents to retrieve current weather, forecasts, and temperature ranges by city or coordinates.
    4 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Wraps the OpenWeatherMap API to provide weather data through MCP, enabling AI agents to query current conditions, forecasts, and other weather information via natural language.
    452 npm
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides weather data from WeatherAPI.com through MCP, enabling AI agents to query current conditions and forecasts via natural language.
    195 npm
    MIT