코드 작성 전 MCP 이해: 진화, 아키텍처, 일회성 통합을 넘는 이유
Model Context Protocol은 Anthropic이 2024년 11월 공개한 개방 표준으로, AI 클라이언트가 외부 역량을 발견·호출하는 방식을 통일합니다. Server를 한 번 작성하면 Claude Desktop, Cursor, MCP 호환 클라이언트에서 연결하고, 하위 LLM을 바꿔도 도구 계층을 다시 작성할 필요가 없습니다.
Function Calling 시대: LLM 벤더마다 독자 스키마를 제공했습니다. GPT, Claude, Gemini 각각 별도 어댑터 코드가 필요했습니다.
Plugins 물결: ChatGPT Plugins가 실시간 데이터 수요를 증명했으나 OpenAI 전용·폐쇄 생태계에 머물렀습니다.
MCP 표준: Anthropic이 벤더 중립 프로토콜을 오픈소스로 공개했고, 2026년에는 OpenAI·Google·Microsoft가 Linux Foundation AAIF 거버넌스 아래 채택했습니다.
설계 목표: HTTP가 웹 서비스를 표준화한 것처럼 AI-도구 통신을 표준화합니다. 단일 wire format, 런타임 발견, 자기 설명형 도구입니다.
┌────────────────────┐ ┌─────────────────────┐
│ MCP Client │ ◄─────► │ MCP Server │
│ (Claude / Cursor) │ JSON │ (직접 구현) │
│ │ -RPC │ │
└────────────────────┘ └─────────────────────┘
│
┌─────────────┼─────────────┐
▼ ▼ ▼
Tools Resources Prompts
(동작) (데이터 읽기) (템플릿)
| 역량 | 역할 | 예시 |
|---|---|---|
| Tools | AI가 호출하는 함수 | 검색, 계산, SQL, HTTP 호출 |
| Resources | URI로 AI가 읽는 데이터 | 설정 파일, 프로필, 노트 인덱스 |
| Prompts | 재사용 프롬프트 템플릿 | 코드 리뷰, 면접 시뮬, 디버그 어시스턴트 |
wire format은 JSON-RPC 2.0입니다. 수명 주기: initialize 핸드셰이크 → 역량 협상 → 요청/응답 루프 → graceful shutdown. 전송은 stdio(로컬 서브프로세스, 네트워크 불필요)와 HTTP + SSE(원격, 다중 클라이언트, 팀 공유)가 주류입니다.
| 차원 | MCP | OpenAI Function Calling | LangChain Tools |
|---|---|---|---|
| 표준화 | 개방 프로토콜 | 벤더 독점 | 프레임워크 종속 |
| 전송 | stdio / HTTP+SSE | HTTP만 | HTTP만 |
| 크로스 모델 | 가능 | 불가 | 부분적 |
| Resources / Prompts | 네이티브 | 미지원 | 미지원 |
| 생태계(2026) | 10,000+ Server | 성숙·잠금 | 성숙·결합 |
MCP는 Function Calling을 감싼 또 하나의 래퍼가 아니라, AI가 런타임에 도구를 발견·기술·호출하게 하는 프로토콜 계층입니다.
환경 구성과 Hello World: venv에서 Cursor에 보이는 도구까지
10분 이내에 동작하는 MCP Server를 만들 수 있습니다. Python + FastMCP를 권장 시작 경로로 삼으며, TypeScript는 @modelcontextprotocol/sdk로 동일 개념을 따릅니다.
| 언어 | SDK | 적합 대상 |
|---|---|---|
| Python | mcp (FastMCP) | 백엔드·AI 엔지니어, 가장 빠른 Hello World |
| TypeScript | @modelcontextprotocol/sdk | Node 기반 프론트·풀스택 팀 |
python -m venv .venv source .venv/bin/activate pip install mcp npm init -y npm install @modelcontextprotocol/sdk
권장 프로젝트 레이아웃은 다음과 같습니다.
my-mcp-server/ ├── server.py ├── tools/ │ ├── calculator.py │ └── web_search.py ├── resources/ │ └── file_reader.py ├── prompts/ │ └── templates.py ├── tests/ │ └── test_tools.py └── pyproject.toml
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-first-server")
@mcp.tool()
def say_hello(name: str) -> str:
return f"Hello, {name}! This is your first MCP tool."
if __name__ == "__main__":
mcp.run()
공식 MCP Inspector로 실행·검증합니다.
python server.py npx @modelcontextprotocol/inspector python server.py
클라이언트 연결: Claude Desktop claude_desktop_config.json 또는 Cursor mcp.json에 Server 실행 명령을 추가합니다. 재시작 후 도구 목록에 표시되고 테스트 호출에 응답하는지 확인합니다.
참고: STDIO Server는 클라이언트가 열려 있는 동안 서브프로세스로 계속 실행되어야 합니다. 설정에는 절대 경로를 쓰십시오. 작업 디렉터리 불일치가 Hello World 실패의 가장 흔한 원인입니다.
Tools, Resources, Prompts: Server가 노출해야 할 세 계층
프로덕션 Server는 동작용 Tools, 읽기용 Resources, 재사용 템플릿 Prompts를 등록합니다. 함수 시그니처와 docstring이 AI 대면 문서가 되므로 별도 OpenAPI 문서가 필수는 아닙니다.
Tool 구조: 이름은 함수명, 매개변수는 타입 힌트, 설명은 docstring에서 가져옵니다. 복잡한 입력에는 Pydantic 모델을 사용합니다.
from pydantic import BaseModel, Field
class SearchInput(BaseModel):
query: str = Field(description="Search keywords")
max_results: int = Field(default=5, description="Max results")
language: str = Field(default="en", description="Result language")
@mcp.tool()
def web_search(input: SearchInput) -> list[dict]:
...
| 실무 Tool | 역할 | 핵심 패턴 |
|---|---|---|
| Calculator | 수식 평가 | 안전 eval 또는 AST 파서, 문자열 반환 |
| File read/write | 로컬 파일 I/O | 허용 디렉터리 화이트리스트 |
| HTTP request | 외부 API 호출 | httpx async, timeout + 상태 검사 |
| Database query | 읽기 전용 SQL | 매개변수화 쿼리, DDL 차단 |
| Time / timezone | 현재 시각, 변환 | ISO 8601 문자열 반환 |
import httpx
@mcp.tool()
async def fetch_url(url: str) -> str:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(url)
response.raise_for_status()
return response.text
오류 처리: 복구 가능한 실패는 구조화된 error dict를 반환하고, 복구 불가 상태만 raise합니다. I/O Tool에는 항상 timeout을 설정하고, 파일시스템·DB 접근 전 권한을 검증합니다.
Resources는 Tools와 다릅니다. Resources는 URI로 데이터를 공급하고 Tools는 동작을 실행합니다. 정적 Resource는 고정 URI, 동적 Resource는 경로 매개변수를 받습니다.
@mcp.resource("config://app-settings")
def get_app_settings() -> str:
return json.dumps({"version": "1.0", "env": "production"})
@mcp.resource("user://{user_id}/profile")
def get_user_profile(user_id: str) -> str:
user = db.query_user(user_id)
return json.dumps(user)
| Resource 유형 | MIME | 용도 |
|---|---|---|
| Text | text/plain, application/json | 설정, 로그, 구조화 데이터 |
| Binary | image/*, application/pdf | 문서, 스크린샷 |
| Streaming | 이벤트 스트림 | 실시간 지표, 파일 감시 |
파일시스템 Resource Server는 디렉터리 목록, 파일 내용 읽기, 변경 이벤트 구독을 제공합니다. Prompts는 동적 매개변수 주입이 가능한 대화 템플릿입니다.
from mcp.types import PromptMessage, TextContent
@mcp.prompt()
def code_review_prompt(language: str, code: str) -> list[PromptMessage]:
return [
PromptMessage(
role="user",
content=TextContent(
type="text",
text=f"Review this {language} code for bugs, security, and performance:\n```{language}\n{code}\n```"
)
)
]
멀티턴 Prompts는 user와 assistant 역할을 혼합합니다. 면접 시뮬, 디버그 워크스루, 온보딩 플로우처럼 세션 간 일관된 구조가 필요할 때 유용합니다.
HTTP 전송, 인증, 디버깅, 자동화 테스트
로컬 STDIO는 개발용입니다. 팀 공유·SaaS 배포에는 HTTP + SSE가 필요합니다. FastMCP는 streamable-http 전송을 최소 코드 변경으로 지원합니다.
| 특성 | stdio | HTTP + SSE |
|---|---|---|
| 배포 | 로컬 서브프로세스 | 원격 서버 |
| 지연 | 거의 없음 | 네트워크 의존 |
| 다중 클라이언트 | 프로세스당 1클라이언트 | 동시 다중 클라이언트 |
| 적합 | 개인 개발 도구 | 팀·프로덕션 SaaS |
mcp = FastMCP("remote-server", transport="streamable-http")
if __name__ == "__main__":
mcp.run(host="0.0.0.0", port=8000)
프로덕션 HTTP Server에는 인증과 가드레일이 필요합니다. Bearer Token 또는 API Key 미들웨어, 알려진 클라이언트 origin으로 제한한 CORS, 외부 API·DB를 치는 Tool endpoint의 rate limiting을 적용합니다.
MCP Inspector는 주 디버그 UI입니다. Server 명령으로 실행하고 Tool을 대화형 호출하며 JSON-RPC 요청/응답 쌍을 검사하고, 클라이언트 연결 전 오류 경로를 시뮬레이션합니다.
import pytest
from mcp.client.session import ClientSession
from mcp.client.stdio import StdioServerParameters, stdio_client
@pytest.mark.asyncio
async def test_calculator_tool():
server_params = StdioServerParameters(
command="python",
args=["server.py"]
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool("calculate", {"expression": "2 + 2"})
assert result.content[0].text == "4"
| 오류 | 원인 | 해결 |
|---|---|---|
| 클라이언트에 Tool 미표시 | 설정 경로·명령 오류 | mcp.json / claude_desktop_config.json 절대 경로 확인 |
| JSON 직렬화 실패 | 직렬화 불가 반환 타입 | str 또는 dict 반환, 커스텀 객체 회피 |
| Timeout disconnect | 동기 Tool의 blocking I/O | async 전환, 명시적 timeout 추가 |
| Permission denied | 화이트리스트 밖 경로 | 허용 디렉터리 명시적 설정 |
프로덕션 배포, 지식베이스 프로젝트, 생태계 선정, 6단계 롤아웃
Hello World에서 프로덕션으로 가려면 컨테이너화, 관측 가능성, 버전 협상, 실질 가치를 증명하는 참조 프로젝트가 필요합니다. 아래 캡스톤은 Cursor 안에서 로컬 Markdown 노트를 의미 검색하는 개인 지식베이스 MCP Server입니다.
역량 목록화: Agent가 필요로 하는 DB 쿼리, 파일 I/O, 사내 API, 빌드 트리거를 나열합니다. 각 항목을 읽기 전용·쓰기로 태깅합니다.
전송 선택: 로컬 개발은 STDIO, 여러 팀원·CI Agent가 안정 호스트의 Server를 공유하면 HTTP+SSE를 선택합니다.
구현과 Schema: 공식 SDK로 Tool을 등록합니다. 모든 매개변수·반환 형태에 JSON Schema를 작성합니다.
클라이언트 설정: Cursor mcp.json 또는 Claude Desktop 설정에 실행 명령 또는 원격 URL을 지정합니다. 필수 env var를 문서화합니다.
발견·호출 테스트: tools/list가 전체 카탈로그를 반환하는지 확인합니다. 샘플 tools/call 체인을 실행하고 다단계 컨텍스트가 유지되는지 검증합니다.
프로덕션 호스트 배포: Docker로 컨테이너화합니다. 빠른 시작은 Railway/Render, 버스트 워크로드는 Cloud Run/Lambda, Apple 툴체인 공존·7×24 가동은 전용 클라우드 Mac을 검토합니다. 가격 페이지를 참고하십시오.
배포 옵션: Docker는 Python 의존성을 깔끔히 묶습니다. Railway·Render는 개인 프로젝트 원클릭 배포를 제공합니다. AWS Lambda·Google Cloud Run은 버스트형 서버리스에 적합합니다. 기존 인프라 팀은 VPS + Nginx 리버스 프록시가 맞습니다. 구조화 로깅, Tool 호출 수 Prometheus 메트릭, Sentry 알림, /health endpoint를 추가합니다. MCP 프로토콜 버전을 선언하고 핸드셰이크에서 역량을 협상해 클라이언트가 업그레이드 시 graceful degrade 하게 합니다.
지식베이스 프로젝트: ChromaDB 또는 Qdrant로 로컬 Markdown을 인덱스하고 text-embedding-3-small로 임베딩하며 watchfiles로 변경을 감시합니다. 노트 인덱싱·의미 검색·쓰기/갱신 세 Tool과 인덱스 파일 목록 Resource를 노출합니다. Cursor에서 "지난주 MCP에 대해 뭐라고 썼지?"라고 물으면 Agent가 검색 Tool을 호출해 관련 스니펫을 반환합니다.
| 커뮤니티 Server | 역량 |
|---|---|
| mcp-server-filesystem | 디렉터리 목록, 파일 읽기/쓰기 |
| mcp-server-github | 이슈, PR, 코드 검색 |
| mcp-server-brave-search | Brave API 웹 검색 |
| mcp-server-postgres | 매개변수화 SQL 쿼리 |
| mcp-server-slack | 채널 메시지·게시 |
2026년 주요 AI 클라이언트는 네이티브 MCP 지원을 제공합니다. 마켓플레이스에 수천 Server가 등록되며, 엔터프라이즈 채택이 OAuth 2.0 인증 표준과 노출 endpoint 보안 감사를 촉진합니다. 다음 단계: modelcontextprotocol.io에서 전체 스펙을 읽고, 첫 Server를 공개하며, Agent Skill과 MCP를 결합해 오케스트레이션 워크플로를 구성합니다.
MCP 생태계 규모(2026): 공개 MCP Server 수는 10,000을 넘으며, 초기 HTTP 웹 성장과 유사한 네트워크 효과가 관측됩니다(openEuler / Jacar 커뮤니티 집계).
통합 비용 절감: MCP 표준화는 벤더별 어댑터 대비 AI 도구 통합 개발 비용을 38–55% 줄입니다(Atlan / WorkOS 업계 분석).
스타트업 진입 장벽: 표준화된 Tool 인터페이스는 AI 스타트업 진입 장벽을 약 62% 낮추고, 전통 SI 맞춤 작업은 약 43% 감소합니다(업계 설문).
| 방식 | 프로덕션 MCP Server | 주요 약점 |
|---|---|---|
| 노트북 STDIO | 빠른 로컬 개발 | 덮개 닫으면 프로세스 종료, 7×24 불가 |
| 범용 Linux VPS | HTTP+SSE 배포 가능 | Apple 툴체인·iOS CI 불일치 |
| 서버리스(Lambda/Cloud Run) | 버스트 트래픽 저운영 | 콜드 스타트, stateful 세션 한계 |
| KVMNODE 클라우드 Mac + MCP | 전용 노드, launchd, 스냅샷 롤백 | 대여 계획 필요 |
대안을 솔직히 비교하면 주력 MacBook에서 HTTP+SSE를 돌리면 덮개를 닫거나 OS 업데이트 시 끊깁니다. 세션 affinity 없는 서버리스는 다단계 Agent 컨텍스트를 잃습니다. 인증 없이 MCP endpoint를 노출하면 prompt injection과 무단 Tool 호출 위험이 커집니다. 2026년 감사에서 약 1,000개의 무보호 Server가 색인되었습니다. Apple Silicon, 7×24 가동, MCP Server·iOS CI·Agent Gateway 워크로드 격리가 필요한 팀에는 KVMNODE Mac Mini M4/M4 Pro 전용 대여가 현실적입니다. 일/주/월 유연 과금, launchd 관리 프로세스, 스냅샷 롤백. 가격 페이지, 고객 센터, 주문 페이지에서 노트북을 닫은 뒤에도 MCP 스택이 유지되는 호스트를 확보할 수 있습니다.