MCP(Model Context Protocol)๋Š” Anthropic์ด 2024๋…„ 11์›”์— ๋ฐœํ‘œํ•œ ์˜คํ”ˆ ํ‘œ์ค€ ํ”„๋กœํ† ์ฝœ๋กœ, AI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(Claude, ChatGPT ๋“ฑ)์ด ์™ธ๋ถ€ ์‹œ์Šคํ…œ(DB, ํŒŒ์ผ, API ๋“ฑ)๊ณผ ํ‘œ์ค€ํ™”๋œ ๋ฐฉ์‹์œผ๋กœ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

USB-C ํฌํŠธ ๋น„์œ : USB-C๊ฐ€ ์ „์ž๊ธฐ๊ธฐ๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ํ‘œ์ค€์ด๋“ฏ, MCP๋Š” AI ์•ฑ์„ ์™ธ๋ถ€ ์‹œ์Šคํ…œ์— ์—ฐ๊ฒฐํ•˜๋Š” ํ‘œ์ค€์ด๋‹ค.

MCP Server๋Š” ์ด ํ”„๋กœํ† ์ฝœ์—์„œ ์ปจํ…์ŠคํŠธ๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์˜๋ฏธํ•œ๋‹ค. ์ฆ‰, AI๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ(tool)๋‚˜ ๋ฐ์ดํ„ฐ(resource)๋ฅผ ๋…ธ์ถœํ•˜๋Š” ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค.

ํ•ด๋‹น ๊ฐœ๋…์ด ํ•„์š”ํ•œ ์ด์œ 

  • AI ์•ฑ์—์„œ ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ(DB, API ๋“ฑ)์— ์ ‘๊ทผํ•˜๋ ค๋ฉด ๊ฐ๊ฐ ์ปค์Šคํ…€ ์ปค๋„ฅํ„ฐ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ–ˆ๋‹ค (Nร—M ๋ฌธ์ œ)
  • MCP๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•˜๋‚˜์˜ ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ชจ๋“  AI ์•ฑ์ด ๋™์ผํ•œ ์„œ๋ฒ„์— ์ ‘์† ๊ฐ€๋Šฅ
  • Claude Code, Codex CLI ๋“ฑ์—์„œ ๋‚ด DB์˜ Todo ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ์กฐํšŒ/์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค

AS-IS

sequenceDiagram
    autonumber
    participant CC as Claude Code
    participant API as Custom API
    participant DB as Database

    CC->>API: ์ง์ ‘ HTTP ํ˜ธ์ถœ (์ปค์Šคํ…€ ์ฝ”๋“œ ํ•„์š”)
    API->>DB: SQL ์ฟผ๋ฆฌ
    DB-->>API: ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜
    API-->>CC: JSON ์‘๋‹ต
    Note over CC,DB: ๊ฐ AI ์•ฑ๋งˆ๋‹ค ๋ณ„๋„ ์—ฐ๋™ ์ฝ”๋“œ ํ•„์š”<br/>(Nร—M ๋ฌธ์ œ)

TO-BE

sequenceDiagram
    autonumber
    participant CC as Claude Code
    participant MC as MCP Client
    participant MS as MCP Server
    participant DB as DB

    CC->>MC: "Todo ๋ชฉ๋ก ๋ณด์—ฌ์ค˜"
    MC->>MS: tools/call: getTodos (JSON-RPC)
    MS->>DB: getTodos (DB)
    DB-->>MS: Todo[]
    MS-->>MC: content: [{type: "text", text: "..."}]
    MC-->>CC: ์ž์—ฐ์–ด ์‘๋‹ต ์ƒ์„ฑ
    Note over CC,DB: ํ‘œ์ค€ ํ”„๋กœํ† ์ฝœ๋กœ ์–ด๋–ค AI ์•ฑ์ด๋“ <br/>๋™์ผํ•œ MCP Server ์žฌ์‚ฌ์šฉ

MCP ์•„ํ‚คํ…์ฒ˜: 3๊ฐ€์ง€ ์ฐธ์—ฌ์ž

์ฐธ์—ฌ์ž์—ญํ• ์˜ˆ์‹œ
MCP HostAI ์•ฑ, MCP Client๋ฅผ ๊ด€๋ฆฌClaude Code, Claude Desktop, VS Code
MCP ClientMCP Server์™€ 1:1 ์—ฐ๊ฒฐ ์œ ์ง€Host ๋‚ด๋ถ€์—์„œ ์ž๋™ ์ƒ์„ฑ๋จ
MCP Server์ปจํ…์ŠคํŠธ(Tool, Resource)๋ฅผ ์ œ๊ณตPrisma Todo ์„œ๋ฒ„
graph TB
    subgraph "MCP Host (Claude Code)"
        Client1["MCP Client 1"]
        Client2["MCP Client 2"]
    end

    ServerA["MCP Server A<br/>(Todo - Prisma)"]
    ServerB["MCP Server B<br/>(ํŒŒ์ผ์‹œ์Šคํ…œ)"]

    Client1 ---|"STDIO"| ServerA
    Client2 ---|"STDIO"| ServerB

MCP์˜ 2๊ฐ€์ง€ ๋ ˆ์ด์–ด

Data Layer (JSON-RPC 2.0)

ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ๊ฐ„ ๋ฉ”์‹œ์ง€ ๊ตฌ์กฐ์™€ ์˜๋ฏธ๋ฅผ ์ •์˜ํ•œ๋‹ค.

  • Lifecycle: ์—ฐ๊ฒฐ ์ดˆ๊ธฐํ™” โ†’ ๊ธฐ๋Šฅ ํ˜‘์ƒ(capability negotiation) โ†’ ์ข…๋ฃŒ
  • Server Primitives: Tools, Resources, Prompts
  • Client Primitives: Sampling, Elicitation, Logging

Transport Layer

ํ†ต์‹  ์ฑ„๋„๊ณผ ์ธ์ฆ์„ ๊ด€๋ฆฌํ•œ๋‹ค.

Transport์„ค๋ช…MCP ์„œ๋ฒ„ ์œ„์น˜์‚ฌ์šฉ ์‹œ์ 
STDIOstdin/stdout ์ŠคํŠธ๋ฆผ๊ฐ™์€ ์ปดํ“จํ„ฐ (๋กœ์ปฌ)๋กœ์ปฌ ํ”„๋กœ์„ธ์Šค
Streamable HTTPHTTP POST + SSE๋‹ค๋ฅธ ์ปดํ“จํ„ฐ (์›๊ฒฉ ์„œ๋ฒ„)์›๊ฒฉ ์„œ๋ฒ„

๋ ˆ์ด์–ด ์ดํ•ด๋ฅผ ์œ„ํ•œ ๋น„์œ 

์šฐ์ฒด๊ตญ ์‹œ์Šคํ…œ์— ๋น„์œ :

๋ ˆ์ด์–ด์—ญํ• ์šฐ์ฒด๊ตญ ๋น„์œ ์‹ค์ œ MCP ์˜ˆ์‹œ
Transport Layer์–ด๋–ค ์šด์†ก ์ˆ˜๋‹จ?๐Ÿš— ํƒ๋ฐฐ์ฐจ vs โœˆ๏ธ ๋น„ํ–‰๊ธฐSTDIO vs HTTP
Data LayerํŽธ์ง€ ๋‚ด์šฉ๊ณผ ํ˜•์‹๐Ÿ“ ํŽธ์ง€ ํฌ๋งท (๋ฐœ์‹ ์ž, ์ˆ˜์‹ ์ž, ๋ณธ๋ฌธ)JSON-RPC ๋ฉ”์‹œ์ง€ (tools/list, tools/call)

์˜ˆ์‹œ:

  • Transport Layer: โ€œ์ด ํŽธ์ง€๋ฅผ ํƒ๋ฐฐ์ฐจ(STDIO)๋กœ ๋ณด๋‚ผ๊นŒ, ๋น„ํ–‰๊ธฐ(HTTP)๋กœ ๋ณด๋‚ผ๊นŒ?โ€
  • Data Layer: โ€œํŽธ์ง€์— ์–ด๋–ค ๋‚ด์šฉ(tools/list ์š”์ฒญ)์„ ์–ด๋–ค ํ˜•์‹(JSON-RPC)์œผ๋กœ ์ ์„๊นŒ?โ€

์‹ค์ œ ๋™์ž‘:

sequenceDiagram
    autonumber
    participant Client as MCP Client
    participant Server as MCP Server

    Note over Client,Server: Transport Layer: STDIO๋กœ ๋ฌผ๋ฆฌ์  ์ „์†ก
    Client->>Server: {"method":"tools/list"} (Data Layer)
    Note over Server: JSON-RPC ๋ฉ”์‹œ์ง€ ํ•ด์„
    Server-->>Client: {"result":{"tools":[...]}} (Data Layer)
    Note over Client: ์‘๋‹ต ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ
  • Transport Layer: STDIO๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฌผ๋ฆฌ์ ์œผ๋กœ ์ „์†ก๋จ
  • Data Layer: JSON-RPC ํ˜•์‹์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์˜๋ฏธ์ ์œผ๋กœ ํ•ด์„๋จ

3๋Œ€ Server Primitives (ํ•ต์‹ฌ)

MCP Server๊ฐ€ ๋…ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” 3๊ฐ€์ง€ ํ•ต์‹ฌ ์š”์†Œ:

1. Tools (๋„๊ตฌ)

  • AI๊ฐ€ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜ (e.g. getTodos, createTodo)
  • tools/list๋กœ ๋ฐœ๊ฒฌ, tools/call๋กœ ์‹คํ–‰
  • inputSchema๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž… ์ •์˜ (JSON Schema)

2. Resources (๋ฆฌ์†Œ์Šค)

  • ์ฝ๊ธฐ ์ „์šฉ ๋ฐ์ดํ„ฐ ์ œ๊ณต (ํŒŒ์ผ ๋‚ด์šฉ, DB ์Šคํ‚ค๋งˆ ๋“ฑ)
  • resources/list๋กœ ๋ฐœ๊ฒฌ, resources/read๋กœ ์กฐํšŒ

3. Prompts (ํ”„๋กฌํ”„ํŠธ)

  • ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ…œํ”Œ๋ฆฟ (์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ, few-shot ์˜ˆ์‹œ)
  • prompts/list๋กœ ๋ฐœ๊ฒฌ, prompts/get์œผ๋กœ ์กฐํšŒ

TypeScript๋กœ MCP Server ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•

1. ํ”„๋กœ์ ํŠธ ์…‹์—…

mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod@3
npm install -D @types/node typescript

2. Tool ๋“ฑ๋ก (ํ•ต์‹ฌ ์ฝ”๋“œ ํŒจํ„ด)

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
 
const server = new McpServer({
  name: "my-server",
  version: "1.0.0",
});
 
// Tool ๋“ฑ๋ก
server.registerTool(
  "getTodos",
  {
    description: "Get all todos from the database",
    inputSchema: {},  // ํŒŒ๋ผ๋ฏธํ„ฐ ์—†์Œ
  },
  async () => {
    // Prisma๋กœ DB ์กฐํšŒ
    const todos = await prisma.todo.findMany();
    return {
      content: [{ type: "text", text: JSON.stringify(todos) }],
    };
  }
);
 
// ์„œ๋ฒ„ ์‹œ์ž‘ (STDIO transport)
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
}
main();

3. Claude Code์— ๋“ฑ๋ก

~/.claude/settings.json:

{
  "mcpServers": {
    "todo-server": {
      "command": "node",
      "args": ["/absolute/path/to/build/index.js"]
    }
  }
}

ํ”„๋กœํ† ์ฝœ ํ†ต์‹  ํ๋ฆ„ (์‹ค์ œ JSON-RPC ๋ฉ”์‹œ์ง€)

sequenceDiagram
    autonumber
    participant Client as MCP Client
    participant Server as MCP Server

    Note over Client,Server: 1. ์ดˆ๊ธฐํ™” (Lifecycle)
    Client->>Server: initialize {protocolVersion, capabilities}
    Server-->>Client: {capabilities: {tools: {}}}
    Client->>Server: notifications/initialized

    Note over Client,Server: 2. ๋„๊ตฌ ๋ฐœ๊ฒฌ (Discovery)
    Client->>Server: tools/list
    Server-->>Client: {tools: [{name: "getTodos", ...}]}

    Note over Client,Server: 3. ๋„๊ตฌ ์‹คํ–‰ (Execution)
    Client->>Server: tools/call {name: "getTodos"}
    Server-->>Client: {content: [{type: "text", text: "[...]"}]}

STDIO Transport

STDIO(Standard Input/Output) Transport๋Š” ๊ฐ™์€ ๋จธ์‹ ์—์„œ ์‹คํ–‰๋˜๋Š” ๋‘ ํ”„๋กœ์„ธ์Šค ๊ฐ„ ํ†ต์‹  ๋ฐฉ์‹์ด๋‹ค.

ํ•ต์‹ฌ ์›๋ฆฌ:

  • ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค(Claude Code)๊ฐ€ ์ž์‹ ํ”„๋กœ์„ธ์Šค(MCP Server)๋ฅผ spawn
  • ๋ถ€๋ชจ โ†’ ์ž์‹: stdin์œผ๋กœ JSON-RPC ๋ฉ”์‹œ์ง€ ์ „์†ก
  • ์ž์‹ โ†’ ๋ถ€๋ชจ: stdout์œผ๋กœ JSON-RPC ์‘๋‹ต ์ „์†ก

์™œ console.log() ๊ธˆ์ง€์ธ๊ฐ€:

  • stdout์€ JSON-RPC ๋ฉ”์‹œ์ง€ ์ „์šฉ ์ฑ„๋„
  • console.log("hello")๊ฐ€ stdout์— ์“ฐ์ด๋ฉด โ†’ ํด๋ผ์ด์–ธํŠธ๊ฐ€ "hello"๋ฅผ JSON-RPC๋กœ ํŒŒ์‹ฑ ์‹œ๋„ โ†’ ํŒŒ์‹ฑ ์—๋Ÿฌ๋กœ ์„œ๋ฒ„ ํฌ๋ž˜์‹œ
  • ๋””๋ฒ„๊น… ๋กœ๊ทธ๋Š” ๋ฐ˜๋“œ์‹œ console.error() (stderr)๋กœ ์ถœ๋ ฅ

STDIO vs HTTP ๋น„๊ต:

STDIOStreamable HTTP
์‹คํ–‰ ์œ„์น˜๋กœ์ปฌ (๊ฐ™์€ ๋จธ์‹ )์›๊ฒฉ ๊ฐ€๋Šฅ
์—ฐ๊ฒฐ ๋ฐฉ์‹ํ”„๋กœ์„ธ์Šค spawnHTTP ์š”์ฒญ
ํด๋ผ์ด์–ธํŠธ ์ˆ˜1:11:N
๋„คํŠธ์›Œํฌ ์˜ค๋ฒ„ํ—ค๋“œ์—†์Œ์žˆ์Œ

์ฐธ๊ณ  ๋ฌธ์„œ