PromleeBlog
sitemapaboutMe

posting thumbnail
MCP 서버를 TypeScript SDK로 구축하는 방법
Building an MCP Server with TypeScript SDK

📅

🚀

들어가기 전에🔗

이번 포스팅에서는 *Model Context Protocol(MCP)*의 TypeScript SDK를 사용하여 MCP 서버를 구축하는 방법을 알아보겠습니다. 이 글에서는 MCP가 무엇인지, 그리고 TypeScript SDK를 활용하여 MCP 서버를 단계별로 만드는 과정을 아주 자세하게 설명드리겠습니다.

🚀

Model Context Protocol(MCP)란?🔗

먼저, MCP에 대해 간단히 알아보겠습니다. MCP는 *대형 언어 모델(LLM)*이 외부 데이터와 기능에 안전하고 표준화된 방식으로 접근할 수 있도록 해주는 프로토콜입니다. 쉽게 말해, LLM이 필요한 정보를 외부에서 가져오거나 특정 작업을 수행할 수 있도록 돕는 다리 역할을 합니다. 예를 들어, LLM이 날씨 정보를 필요로 할 때, MCP를 통해 실제 날씨 API에 접근하여 정보를 가져올 수 있습니다. MCP 공식 문서에서 더 자세한 정보를 확인하실 수 있습니다.

🚀

TypeScript SDK를 사용하여 MCP 서버 구축하기🔗

이제 TypeScript SDK를 사용하여 MCP 서버를 구축하는 과정을 단계별로 살펴보겠습니다.

1. 프로젝트 초기 설정🔗

먼저, 새로운 디렉토리를 만들고 프로젝트를 초기화합니다.
mkdir my-mcp-server
cd my-mcp-server
npm init -y
이렇게 하면 my-mcp-server라는 폴더가 생성되고, 그 안에서 npm 프로젝트가 초기화됩니다.

2. 필수 패키지 설치🔗

다음으로, MCP 서버를 구축하는 데 필요한 패키지들을 설치합니다.
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node
여기서 @modelcontextprotocol/sdk는 MCP의 TypeScript SDK이며, zod는 데이터 검증을 위한 라이브러리입니다. typescript@types/node는 TypeScript 개발을 위한 필수 패키지입니다.

3. TypeScript 설정 파일 생성🔗

프로젝트 루트에 tsconfig.json 파일을 생성하여 TypeScript 컴파일러의 설정을 지정합니다.
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "Node",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true
  },
  "include": ["src"]
}
이 설정은 최신 JavaScript 문법을 사용하고, 모듈 시스템을 ESNext로 지정하며, 소스 코드는 src 폴더에, 컴파일된 코드는 dist 폴더에 위치하도록 합니다.

4. 소스 코드 디렉토리 및 진입점 파일 생성🔗

src 디렉토리를 만들고, 그 안에 index.ts 파일을 생성합니다.
mkdir src
touch src/index.ts
이제 src/index.ts 파일에 MCP 서버의 코드를 작성할 준비가 되었습니다.

5. MCP 서버 구현🔗

이제 실제로 MCP 서버를 구현해보겠습니다. 간단한 계산기 기능과 인사말을 제공하는 서버를 만들어보겠습니다.
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
 
const server = new McpServer({
  name: "Demo",
  version: "1.0.0"
});
 
server.tool(
  "add",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }]
  })
);
 
server.resource(
  "greeting",
  new ResourceTemplate("greeting://{name}", { list: undefined }),
  async (uri, { name }) => ({
    contents: [{
      uri: uri.href,
      text: `안녕하세요, ${name}님!`
    }]
  })
);
 
const transport = new StdioServerTransport();
await server.connect(transport);
이 코드는 MCP 서버를 생성하고 add라는 이름의 도구(tool)를 추가하여 두 숫자의 합을 계산하는 기능을 제공합니다. 또한 greeting이라는 리소스를 추가하여 사용자의 이름에 따라 동적으로 인사말을 생성합니다. 마지막으로 표준 입출력을 통해 메시지를 처리합니다.

6. 서버 빌드 및 실행🔗

이제 MCP 서버를 빌드하고 실행해보겠습니다. 먼저 TypeScript 코드를 컴파일한 후, 실행합니다.
npx tsc
node dist/index.js
정상적으로 실행되면, MCP 서버가 표준 입력을 기다리는 상태가 되며 클라이언트와의 통신이 가능해집니다.
➡️

npm 스크립트로 자동화하기🔗

매번 npx tscnode dist/index.js를 입력하는 것이 번거롭다면, package.jsonscripts 항목을 다음과 같이 수정해보세요.
"scripts": {
  "build": "tsc",
  "start": "node dist/index.js",
  "dev": "npm run build && npm run start"
}
이제 다음 명령어로 MCP 서버를 빌드하고 실행할 수 있습니다.
npm run dev
개발 중에는 이 스크립트를 사용하면 더욱 편리하게 반복 실행할 수 있습니다.

🚀

문제 발생 및 해결🔗

문제 1: 모듈 해석 오류🔗

오류 메시지
:
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '@modelcontextprotocol/sdk/server/mcp.js'
해결 방법
:
TypeScript에서 ES 모듈을 사용할 때는 .js 확장자를 반드시 명시해야 합니다. 또한 tsconfig.jsonmoduleResolutionNode로 설정했는지 확인해 주세요.

문제 2: 타입 정의 누락🔗

오류 메시지
:
Cannot find name 'process'.
해결 방법
:
@types/node가 설치되어 있어야 하며, tsconfig.json에 다음과 같은 내용을 추가해 주세요.
{
  "compilerOptions": {
    "types": ["node"]
  }
}

🚀

결론🔗

이번 글에서는 MCP의 개념부터 시작하여 TypeScript SDK를 통해 MCP 서버를 구축하는 과정을 차근차근 살펴보았습니다. MCP를 이용하면 LLM이 외부 데이터와 기능을 보다 안전하고 일관된 방식으로 사용할 수 있게 됩니다. SDK가 잘 정리되어 있어 비교적 쉽게 서버를 만들 수 있으므로, 다양한 기능 확장에 도전해보시길 바랍니다.

더 생각해 보기🔗

참고🔗