MCP Servers

A collection of Model Context Protocol servers, templates, tools and more.

MCP 기초 설명

Created 6/12/2026
Updated about 3 hours ago
Repository documentation and setup instructions

MCP 기초 — 통신 구조 이해하기

이 레포는 MCP(Model Context Protocol)가 실제로 어떻게 동작하는지를
코드와 함께 설명합니다.

worker.js는 이 README가 설명하는 내용을 그대로 구현한 최소한의 MCP 서버입니다.


1. MCP가 하는 일

Claude(클라이언트)와 외부 도구(서버) 사이에서 표준화된 방식으로 데이터를 주고받는 규약입니다.

Claude Desktop / claude.ai
        │
        │  "get_fillet_r 실행해줘, keyword = 부드러운"
        ▼
   MCP 서버 (worker.js)
        │
        │  "{ r: 5 }"
        ▼
        Claude

2. 3가지 연결 방식

MCP 서버에 붙는 방법은 세 가지입니다.

STDIO (로컬 프로세스)

Claude Desktop
      │  (프로세스 직접 실행)
      ▼
  server.py / server.js
  (내 컴퓨터에서 실행)
  • Claude Desktop이 서버 프로그램을 직접 실행하고, stdin/stdout으로 통신
  • 사례: RhinoMCP, 파일시스템 MCP 등 로컬 도구
  • 설정 예시:
{
  "mcpServers": {
    "rhino": {
      "command": "python",
      "args": ["C:/rhino_mcp/server.py"]
    }
  }
}

HTTP + SSE (원격 서버)

Claude Desktop / claude.ai
      │  (HTTP 요청)
      ▼
  원격 서버 (Cloudflare Workers 등)
  • URL만 등록하면 누구나 접근 가능
  • 사례: caffeineworks MCP, 이 레포의 worker.js
  • 설정 예시:
{
  "mcpServers": {
    "my-server": {
      "url": "https://my-mcp.workers.dev/mcp"
    }
  }
}

Streamable HTTP (신규 표준)

  • HTTP + SSE의 후속, 2025년 공식화
  • 단일 엔드포인트로 단순화된 방식
  • 현재 이 레포의 구현 방식

3. 3가지 통신 구조

MCP는 JSON-RPC 2.0 형식으로 메시지를 주고받습니다.

요청 (Request) — 클라이언트 → 서버

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_fillet_r",
    "arguments": { "keyword": "부드러운" }
  }
}

| 필드 | 역할 | |------|------| | jsonrpc | 항상 "2.0" 고정 | | id | 요청-응답 매칭용 번호 | | method | 무엇을 요청하는지 | | params | 요청 데이터 |

응답 (Response) — 서버 → 클라이언트

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      { "type": "text", "text": "{ \"r\": 5 }" }
    ]
  }
}
  • id가 요청과 일치해야 함
  • result.content는 배열, 각 항목은 type과 내용으로 구성

에러 응답

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32601,
    "message": "Tool not found"
  }
}

4. 연결할 때 벌어지는 일 (핸드셰이크)

Claude가 MCP 서버에 처음 붙으면 이 순서로 진행됩니다.

Claude                    MCP 서버
  │                          │
  │──── initialize ─────────▶│  "나는 Claude야, 뭘 할 수 있어?"
  │◀─── result ──────────────│  "나는 shape-server야"
  │                          │
  │──── tools/list ─────────▶│  "툴 목록 줘"
  │◀─── result ──────────────│  [툴 이름, 설명, 파라미터 스키마]
  │                          │
  │──── tools/call ─────────▶│  "get_fillet_r 실행해줘"
  │◀─── result ──────────────│  "{ r: 5 }"

5. 서버가 반드시 응답해야 하는 메서드

| 메서드 | 역할 | |--------|------| | initialize | 서버 이름, 버전, 기능 목록 반환 | | tools/list | 툴 이름 + 설명 + 파라미터 스키마 반환 | | tools/call | 실제 툴 실행 후 결과 반환 |

이 세 가지에 응답할 수 있으면 MCP 서버입니다.


6. 툴 스키마 — Claude가 툴을 이해하는 방법

tools/list에서 반환하는 스키마가
Claude가 "언제, 어떻게 이 툴을 호출할지" 판단하는 근거입니다.

{
  "name": "get_fillet_r",
  "description": "디자인 감성어를 입력하면 Rhino 모델링에 쓸 Fillet R 수치(mm)를 반환한다",
  "inputSchema": {
    "type": "object",
    "properties": {
      "keyword": {
        "type": "string",
        "description": "디자인 감성 형용사. 예: 부드러운, 단단한, 따뜻한"
      }
    },
    "required": ["keyword"]
  }
}

중요: description이 부실하면 Claude가 엉뚱하게 호출합니다.
"Fillet R 수치를 반환한다"처럼 무엇을 반환하는지 명확하게 쓰세요.


7. 코드와 README의 1:1 대응

worker.js의 구조는 이 README와 정확히 대응됩니다.

worker.js
├── SECTION A: 키워드-수치 데이터 (JSON)     ← 서버의 "두뇌"
├── SECTION B: initialize 응답               ← 핸드셰이크 4번
├── SECTION C: tools/list 응답              ← 툴 스키마 6번
├── SECTION D: tools/call 응답              ← 실제 실행
└── SECTION E: HTTP 요청 라우팅             ← 연결 방식 2번

코드를 읽을 때 각 SECTION 주석을 기준으로 이 README와 대조하며 보세요.


8. 직접 수정해보기

worker.jsSECTION A만 수정하면 서버의 동작이 바뀝니다.

// SECTION A: 키워드-수치 데이터 ← 여기만 고치면 됩니다
const FILLET_DATA = {
  "부드러운": 8,
  "단단한": 1,
  "따뜻한": 6,
  // 원하는 키워드와 수치를 여기에 추가하세요
};

나중에는 이 데이터를 별도 JSON 파일로 분리하거나,
임베딩 기반으로 고도화할 수 있습니다. (3일차 실습)

Quick Setup
Installation guide for this server

Install Package (if required)

npx @modelcontextprotocol/server-mcp-how-it-works

Cursor configuration (mcp.json)

{ "mcpServers": { "caffeineworks-ai-mcp-how-it-works": { "command": "npx", "args": [ "caffeineworks-ai-mcp-how-it-works" ] } } }