Issue 01중국 AI
AC POST
중국 AI 목록
掘金2026년 9월 17일 08:46중국어 → 한국어

MCP 서버 직접 구현해 Copilot이 사칙연산 도구 호출하게 하기

MCP 개념부터 시작해 사칙연산만 처리하는 Node.js 기반 MCP 서버를 직접 만들고, VS Code의 GitHub Copilot Chat에 연결해 자연어로 도구를 호출하는 과정을 다룬다.

중국어 원문을 AI로 번역했습니다. 고유명사와 수치는 원문 표기를 우선하며, 중요한 판단에는 아래 출처 원문을 함께 확인하세요.

이 글은 「MCP란 무엇인가」부터 시작해, 덧셈·뺄셈·곱셈·나눗셈만 하는 MCP Server를 직접 작성하고(Node.js 구현), 마지막으로 이를 VS Code의 GitHub Copilot Chat에 연결해 자연어로 AI가 우리가 만든 도구를 호출하도록 하는 과정을 다룬다.

1. MCP란 무엇인가

MCP(Model Context Protocol, 모델 컨텍스트 프로토콜)는 AI 애플리케이션과 외부 도구 / 데이터 / 서비스 사이의 연결 방식을 표준화하기 위한 개방형 프로토콜이다.

한 문장으로 이해하면:

MCP는 마치 AI 세계의 USB-C 인터페이스와 같다. 예전에는 도구를 하나 연결할 때마다 전용 어댑터 코드를 한 세트씩 작성해야 했지만, 이제는 모두가 같은 프로토콜로 대화하니 꽂기만 하면 쓸 수 있다.

MCP가 등장하기 전에는 N개의 AI 애플리케이션(VS Code, Claude Desktop, Cursor, 자체 개발 Agent…)과 M개의 도구(GitHub, 데이터베이스, 파일 시스템, 내부 API…)가 있다면 이론적으로 N × M 개의 어댑터 코드를 작성해야 했다:

AI 애플리케이션   도구 ┌─────────┐   ┌─────────┐ │ VS Code │──────│ GitHub │ ├─────────┤   ├─────────┤ │ Claude │──────│ MySQL │ ├─────────┤   ├─────────┤ │ Cursor │──────│ 내부 API │ └─────────┘   └─────────┘ N 개   M 개 연결선 개수 = N × M

MCP가 생긴 후에는 도구가 MCP 프로토콜에 따라 능력을 한 번만 노출하면, MCP를 지원하는 모든 AI 애플리케이션이 접속할 수 있으므로 연결선 개수가 N × M에서 N + M으로 바뀐다:

AI 애플리케이션   MCP 프로토콜   MCP Server ┌─────────┐   ┌─────────┐ │ VS Code │──┐   ┌──│ GitHub │ ├─────────┤ │   │ ├─────────┤ │ Claude │──┼── MCP ──────┼──│ MySQL │ ├─────────┤ │   │ ├─────────┤ │ Cursor │──┘   └──│ 내부 API | └─────────┘   └─────────┘ 연결선 개수 = N + M

MCP의 적용 범위

MCP는 오직 「컨텍스트 교환」이라는 한 가지 일에만 집중한다:

- AI 애플리케이션과 MCP Server 사이에서 어떻게 통신하는지를 규정한다;

- AI 애플리케이션이 대규모 모델을 어떻게 사용해야 하는지는 규정하지 않는다;

- AI 애플리케이션이 받아온 컨텍스트를 어떻게 관리해야 하는지는 규정하지 않는다.

2. MCP의 핵심 개념

2.1 세 가지 참여자

MCP는 클라이언트-서버(Client-Server) 구조를 채택한다:

- MCP Host(호스트): AI 애플리케이션 자체로, 예를 들어 VS Code, Claude Desktop, Claude Code가 있다. 하나 또는 여러 개의 MCP Client를 조율하고 관리하는 역할을 맡는다.

- MCP Client(클라이언트): Host 내부에서 각 MCP Server마다 생성되는 연결 객체로, 특정 Server와의 전용 연결을 유지하는 역할을 맡는다.

- MCP Server(서버): 실제로 컨텍스트와 능력을 제공하는 프로그램으로, 로컬에서 돌릴 수도 있고 원격에서 돌릴 수도 있다.

주의: MCP Server는 「컨텍스트 데이터를 제공하는 프로그램」을 가리키며, 어디에서 실행되는지와는 무관하다.

- 본인 컴퓨터에서 실행되고 stdio로 통신하는 것을 로컬 MCP Server라고 한다;

- 클라우드에서 실행되고 Streamable HTTP로 통신하는 것을 원격 MCP Server라고 한다.

stdio는 standard input/output(표준 입력/출력)의 약자로, 즉 키보드 입력과 콘솔 출력을 말한다. 프로세스 간 통신을 구현할 수 있다.

2.2 서버가 제공할 수 있는 세 가지 능력

MCP Server는 외부에 세 가지 기본 능력(Primitives)을 제공할 수 있다:

능력   설명   대표적 용도 Tools   AI가 호출할 수 있는 실행 가능 함수(사용자 승인 필요)   데이터베이스 조회, API 호출, 계산, 파일 쓰기 Resources   읽기 전용 컨텍스트 데이터 소스   파일 내용, 데이터베이스 레코드, 인터페이스 반환값 Prompts   미리 준비된 프롬프트 템플릿   코드 리뷰 템플릿, 주간 보고서 생성 템플릿

이 글의 실전에서는 Tools만 사용하는데, 계산기가 바로 전형적인 「실행 가능 함수」이기 때문이다.

2.3 두 개의 프로토콜 계층

MCP는 프로토콜을 두 계층으로 나누며, 이 두 계층을 이해하면 MCP의 전체 모습을 대략 이해한 셈이다:

MCP ├── 데이터 계층(Data Layer) → 「무엇을 전달하는가」 │  └── JSON-RPC 2.0 기반: 능력 발견, 버전 협상, Tools / Resources / Prompts / 알림 │ └── 전송 계층(Transport Layer) → 「어떻게 전달하는가」   ├── stdio: 표준 입출력, 프로세스 간 통신, 로컬 배포, 지연 최소   └── Streamable HTTP: HTTP POST(선택적 SSE 스트리밍), 로컬 또는 원격 배포, OAuth 등의 인증 지원

어떤 전송 방식을 쓰든 메시지 자체는 모두 통일되게 JSON-RPC 2.0 형식이다. SDK가 이미 이 계층을 감싸 주었기 때문에, 일상적인 개발에서는 기본적으로 「무엇을 등록했는가」만 신경 쓰면 된다.

JSON-RPC는 JSON 형식에 기반한 원격 프로시저 호출 프로토콜로, 클라이언트가 JSON 요청을 보내 원격 서버의 메서드를 호출하고 결과를 받아올 수 있게 한다.

2.4 MCP와 Function Calling의 차이

많은 사람이 이 둘을 혼동하는데, 실제 관계는 다음과 같다:

차원   Function Calling   MCP 무엇인가   대규모 모델의 한 가지 능력(「어떤 함수를 호출할지」를 출력)   하나의 프로토콜(AI 애플리케이션이 외부 도구/데이터에 어떻게 연결하는지 규정) 해결하는 문제   모델이 도구 호출을 어떻게 결정하는가   도구가 어떻게 온갖 AI 애플리케이션에 표준화되어 접속되는가 코드를 어디에 쓰는가   AI 애플리케이션 내부에 작성   독립적인 Server 프로세스에 작성, 재사용 가능 관계   MCP는 “도구의 콘센트”이고, Function Calling은 “모델이 손을 뻗어 꽂는” 그 동작

간단히 말하면: MCP는 도구를 재사용 가능한 표준 부품으로 만들고, Function Calling은 모델이 그런 표준 부품을 사용할 수 있는 능력을 갖게 한다.

3. 환경 준비

MCP를 구축하려면 공식에서 제공하는 SDK가 필요하다. 이 글에서는 TypeScript 언어 버전의 SDK를 사용한다. Node.js >= 20이 필요하다.

공식 TypeScript/Node SDK(v2)는 Node.js >= 20을 요구한다.

패키지 이름과 관련해서는 버전 차이에 주의해야 한다:

버전   패키지 이름   설명 v1   @modelcontextprotocol/sdk   초기 단일 패키지, 인터넷상 대부분의 튜토리얼이 이것을 사용 v2   @modelcontextprotocol/server   현재 안정 버전, 2026-07-28 버전 MCP 사양 구현

이 글에서는 v2의 @modelcontextprotocol/server를 사용한다(서버 패키지는 이미 독립 패키지로 분리되었고, 클라이언트는 @modelcontextprotocol/client이다).

4. Node.js로 덧셈·뺄셈·곱셈·나눗셈 MCP Server 구현하기

4.1 프로젝트 초기화

mkdir mcp-calculator cd mcp-calculator npm init -y # 의존성 설치: MCP 서버 SDK + zod(도구 입력 파라미터 타입 선언용) npm install @modelcontextprotocol/server zod

package.json을 수정하고 ESM 지원을 추가한다(SDK는 순수 ESM 패키지이다):

{ "name": "mcp-calculator", "version": "1.0.0", "type": "module", "main": "calculator-server.js", "scripts": { "start": "node calculator-server.js" } }

4.2 Server 코드 작성

calculator-server.js를 새로 만든다:

import { McpServer } from "@modelcontextprotocol/server"; import { StdioServerTransport } from "@modelcontextprotocol/server/stdio"; import { z } from "zod";

// 1. MCP Server 인스턴스를 생성한다. name/version은 initialize 응답을 통해 클라이언트에 노출된다. const server = new McpServer({ name: "calculator", version: "1.0.0" });

// 2. 공통 입력 스키마를 뽑아낸다: a, b 모두 숫자이다. const binaryInput = z.object({ a: z.number().describe("첫 번째 피연산자"), b: z.number().describe("두 번째 피연산자"), });

// 3. 통일된 반환 형식을 뽑아낸다: MCP 도구는 반드시 content 배열을 반환해야 한다. const text = (t) => ({ content: [{ type: "text", text: String(t) }] });

// 4. 덧셈 도구를 등록한다. server.registerTool( "add", { title: "덧셈", description: "두 숫자의 합 a + b를 계산한다", inputSchema: binaryInput, }, async ({ a, b }) => text(a + b) );

// 5. 뺄셈 도구를 등록한다. server.registerTool( "subtract", { title: "뺄셈", description: "두 숫자의 차 a - b를 계산한다", inputSchema: binaryInput, }, async ({ a, b }) => text(a - b) );

// 6. 곱셈 도구를 등록한다. server.registerTool( "multiply", { title: "곱셈", description: "두 숫자의 곱 a * b를 계산한다", inputSchema: binaryInput, }, async ({ a, b }) => text(a * b) );

// 7. 나눗셈 도구를 등록한다(0으로 나누기를 처리해야 한다). server.registerTool( "divide", { title: "나눗셈", description: "두 숫자의 몫 a / b를 계산한다, b는 0일 수 없다", inputSchema: binaryInput, }, async ({ a, b }) => { if (b === 0) { return { content: [{ type: "text", text: "오류: 나눗수는 0일 수 없습니다" }], isError: true, }; } return text(a / b); } );

// 8. stdio 전송을 사용해 서비스를 시작한다. const transport = new StdioServerTransport(); await server.connect(transport);

// 주의: stdio 시나리오에서는 로그가 반드시 stderr로 가야 하며, 절대 console.log를 써서는 안 된다. console.error("Calculator MCP Server running on stdio");

4.3 핵심 포인트 설명

1) registerTool(name, config, callback)의 시그니처

server.registerTool("도구 이름(모델이 보게 되는 함수명)", { title: "사용자에게 보여줄 제목", description: "모델에게 보여줄 설명 —— 이 텍스트가 모델이 이 도구를 쓸지 말지, 제대로 쓸지 말지를 직접 결정한다", inputSchema: z.object({ ... }), // 입력 파라미터 타입, SDK가 JSON Schema로 변환한다 outputSchema: z.object({ ... }), // 선택 사항: 반환값 구조 선언 }, async (args, ctx) => { return { content: [{ type: "text", text: "..." }] }; }, );

2) description이 코드보다 더 중요하다

모델은 오직 name + description + inputSchema를 통해서만 이 도구를 호출해야 하는지 판단할 수 있다. 그래서:

- ❌ description: "계산" —— 모델은 덧셈인지 뺄셈인지 모른다;

- ✅ description: "두 숫자의 몫 a / b를 계산하며, b는 0이 될 수 없다" —— 의도가 명확하고 파라미터 의미가 분명하다.

3) stdio 환경에서는 절대 console.log를 쓰면 안 된다

stdio 전송은 표준 출력으로 JSON-RPC 메시지를 전달한다. 로그를 console.log로 한 줄 찍는 순간 JSON-RPC 패킷이 오염되어 연결이 바로 끊어진다.

console.log("server started"); // ❌ stdio 통신을 깨뜨린다 console.error("server started"); // ✅ stderr에 쓰므로 안전하다

4) 오류는 예외를 던지는 대신 isError로 표시해야 한다

예외를 던지면 전체 요청이 실패하지만, isError: true로 하면 오류 정보가 도구 결과로서 모델에게 전달되고, 모델은 이를 근거로 스스로 수정할 수 있다(예를 들어 「제수는 0이 될 수 없다」를 사용자에게 설명해 준다).

4.4 실행해 보기

node calculator-server.js

stdio 서비스는 JSON-RPC 패킷을 기다리고 있기 때문에 터미널에서 「멈춘 것처럼」 보이는 것이 정상이다. 실제로 검증하려면 공식 디버깅 도구인 MCP Inspector를 사용한다:

npx @modelcontextprotocol/inspector node $(pwd)/calculator-server.js

그것이 알려주는 주소를 열면 Web 인터페이스를 볼 수 있다:

- Connect를 클릭;

- Tools 탭으로 전환하고 List Tools를 클릭하면 add / subtract / multiply / divide 네 개의 도구를 볼 수 있다;

- a=6, b=7을 입력하고 multiply를 실행하면 42가 반환된다.

5. VS Code GitHub Copilot에서 이 Server 사용하기

단계 1: mcp.json 설정

VS Code는 mcp.json을 통해 MCP Server를 관리하며, 위치가 두 가지 있다:

- 워크스페이스 레벨: .vscode/mcp.json (권장, git에 커밋해 팀과 공유할 수 있다)

- 사용자 레벨: 명령 팔레트에서 MCP: Open User Configuration 실행 (모든 워크스페이스에서 사용 가능)

mcp-calculator 디렉터리 아래에 .vscode/mcp.json을 새로 만든다:

{ "servers": { "calculator": { "type": "stdio", "command": "node", "args": ["${workspaceFolder}/calculator-server.js"] } } }

필드 설명(stdio 타입):

필드 필수 설명 type 예 stdio(로컬) / http, sse(원격) command 예 실행 명령, PATH에 있어야 하거나 전체 경로를 써야 한다 args 아니오 명령에 전달할 파라미터 배열

${workspaceFolder}에는 실제 파일 디렉터리 경로를 입력해야 한다.

단계 2: Server 시작

설정을 저장하면 mcp.json에서 해당 server 위에 시작 CodeLens가 나타나며, 시작을 클릭한다.

시작하면 VS Code가 프로세스에 연결해 이 Server가 노출하는 도구를 발견한다.

명령 팔레트를 사용할 수도 있다: MCP: List Servers → calculator 선택 → 서버 시작.

단계 3: Copilot Chat에서 도구 활성화

- Chat 뷰 열기(⌃⌘I);

- 대화 모드를 Agent로 전환;

- 입력창의 Configure Tools(도구 구성) 버튼을 클릭하면 펼쳐지면서 calculator라는 MCP Server 아래의 네 개 도구를 볼 수 있다;

- add / subtract / multiply / divide를 체크한다(또는 전부 체크).

단계 4: 자연어로 검증

Agent 모드에서 차례로 입력한다:

(128 * 37) - 456은 얼마인지 계산해 줘?

위 mcp server의 소스 코드는 github 저장소에 업로드되어 있다: github.com/Panda-plus5…

6. 정리

- MCP는 하나의 프로토콜이며, AI 애플리케이션과 외부 도구/데이터 사이의 표준화된 연결 문제를 해결해서 N × M의 어댑테이션 폭발을 N + M으로 바꾼다.

- Host / Client / Server 세 역할은 분담이 명확하다; Server는 Tools / Resources / Prompts 세 가지 능력을 제공한다; 전송 계층은 stdio(로컬) 또는 Streamable HTTP(원격)를 선택할 수 있다.

- v2의 @modelcontextprotocol/server로 MCP Server를 작성하는 데는 세 단계만 필요하다: 인스턴스 생성 → registerTool로 도구 등록 → connect(StdioServerTransport).

- 모델이 도구를 「제대로」 사용하게 하려면 핵심은 도구 내부 로직이 얼마나 복잡한지가 아니라 도구 이름 + description + inputSchema를 다듬는 데 있다.

- VS Code에서 연동하려면 .vscode/mcp.json 한 부만 있으면 된다: 설정 → 시작 → Agent 모드에서 도구 체크 → 자연어로 질문.

7. 참고 링크

- MCP 공식 문서: modelcontextprotocol.io

- MCP 규격(2026-07-28): modelcontextprotocol.io/specificati…

- TypeScript SDK 소스 코드: github.com/modelcontex…

- MCP 공식 Server 참고 구현: github.com/modelcontex…

- MCP Inspector(디버깅 도구): github.com/modelcontex…

- VS Code 공식 문서 《Add and manage MCP servers in VS Code》: code.visualstudio.com/docs/agent-…

- VS Code MCP 설정 참고: code.visualstudio.com/docs/agents…

云浪

88

103k

조회

87

팔로워