패키지와 서브패스 내보내기

패키지와 서브패스 내보내기 (Packages and subpath exports)

MCP TypeScript SDK를 처음 설치하려고 npm 페이지를 열면, 패키지가 아홉 개나 있어서 어느 걸 골라야 할지 막막하죠. 사실 대부분의 프로젝트는 이 중 딱 하나만 설치하면 됩니다. 이 문서에서는 각 패키지가 언제 필요하고, 어떻게 나뉘어 있는지 정리해 볼게요.

한 패키지에서 시작하기

첫 번째 서버 만들기에서 사용한 코드는 전부 @modelcontextprotocol/server 하나만 설치한 것에서 나왔어요. 그런데 이 패키지를 두 개의 import 경로로 가져온다는 점을 눈여겨볼 필요가 있어요.

import { McpServer } from '@modelcontextprotocol/server';
import { serveStdio } from '@modelcontextprotocol/server/stdio';

첫 번째 경로는 패키지의 루트 엔트리예요. 두 번째 경로는 서브패스 내보내기(subpath export) 인데요, 같은 패키지 안에 있는 별개의 입구로 exports 맵에 선언되어 있습니다. 즉 하나의 npm 패키지가 내부에 여러 개의 진입점을 갖고 있는 셈이에요.

프로토콜의 어느 쪽인지에 맞춰 패키지를 고르세요

프로토콜에서 내가 짓는 쪽이 어디인지에 따라 설치할 패키지가 갈립니다.

npm install @modelcontextprotocol/server   # expose tools, resources, prompts
npm install @modelcontextprotocol/client   # connect to servers and call them

이 둘이 거의 모든 작업의 출발점이에요. 한 프로세스가 서버와 클라이언트 역할을 동시에 한다면 둘 다 설치하면 됩니다. 공식적으로 발행된 패키지는 모두 아홉 개예요.

  • @modelcontextprotocol/server@modelcontextprotocol/client — 양쪽을 담당하는 두 출발점.
  • @modelcontextprotocol/node, @modelcontextprotocol/express, @modelcontextprotocol/hono, @modelcontextprotocol/fastify — HTTP로 서빙할 때 쓰는 선택적 어댑터.
  • @modelcontextprotocol/core — 날것의 Zod 와이어 스키마.
  • @modelcontextprotocol/server-legacy@modelcontextprotocol/codemod — v1 코드를 옮길 때 쓰는 마이그레이션 표면.

저장소에 있는 열 번째 패키지 @modelcontextprotocol/core-internal 은 private라서, serverclient 가 빌드 시점에 이것을 묶어 넣기 때문에 여러분의 의존성 트리에는 절대 나타나지 않아요.

Node 전용 코드는 ./stdio 서브패스 뒤에 두세요

StdioClientTransport 는 서버를 자식 프로세스로 띄우므로, 루트 엔트리가 아니라 ./stdio 에서 내보냅니다.

// Runs anywhere: browsers, Workers, Node.
import { Client } from '@modelcontextprotocol/client';
// Spawns a child process — Node-only, so it lives behind the subpath.
import { StdioClientTransport } from '@modelcontextprotocol/client/stdio';

모든 패키지의 루트 엔트리는 런타임 중립(runtime-neutral) 이에요. 그 모듈 그래프는 node:child_process 나 브라우저·Cloudflare Workers 번들러가 풀지 못하는 Node 내장 모듈에 절대 닿지 않습니다. ./stdio 를 import 하는 것이 곧 프로세스 런타임에 들어가겠다고 명시적으로 동의하는 거예요. @modelcontextprotocol/server/stdio 는 서버 쪽 대응물로, serveStdioStdioServerTransport 를 내보냅니다.

v1에서 오셨나요?

v1 의 단일 패키지 @modelcontextprotocol/sdk@modelcontextprotocol/sdk/server/mcp.js 같은 깊은 파일 경로를 노출했어요. v2 패키지는 exports 맵을 선언해서 각 패키지가 이름을 붙인 서브패스만 resolve 되고, import 를 다시 써 주는 작업은 codemod 가 대신 해 줍니다.

HTTP로 서빙할 때는 프레임워크 어댑터를 추가하세요

@modelcontextprotocol/servercreateMcpHandler 는 이미 웹 표준 RequestResponse 객체 위에서 MCP를 서빙합니다. 어댑터 패키지는 그 핸들러를 특정 런타임이나 프레임워크에 연결해 주는 얇은 층이에요. 어댑터는 대상 프레임워크 옆에 함께 설치하면 됩니다.

npm install @modelcontextprotocol/express express

어댑터는 네 개가 있어요. @modelcontextprotocol/node 는 Node 내장 http 서버용이고, Express·Hono·Fastify 용이 각각 하나씩 있죠. 모두 createMcpHandler 위에 얹는 얇은 층이라 MCP 동작 자체를 추가하지는 않습니다.

HTTP로 서빙하기에서 핸들러 자체를 다루고, Express, Hono, Fastify 에 각각 레시피가 있어요.

날것의 와이어 JSON을 검증할 때만 core 를 쓰세요

@modelcontextprotocol/core 는 SDK가 프로토콜 페이로드를 검증할 때 쓰는 Zod 스키마 상수를 내보내요. 게이트웨이·프록시·로그 파이프라인처럼 raw JSON-RPC 페이로드를 직접 다루는 코드를 위한 거예요. serverclient 는 Zod 스키마를 내보내지 않고, 대신 매칭되는 TypeScript 타입을 양쪽 다 함께 실어 보냅니다. 그래서 그냥 registerToolcallTool 만 부르는 상황이라면 직접 import 할 일이 없어요 — serverclient 가 런타임에 공유 스키마 그래프를 여기서 resolve 하므로 전이적으로 딸려오기 때문이죠. 방법은 와이어 스키마에서 다룹니다.

server-legacycodemod 는 마이그레이션 가이드에 맡기세요

@modelcontextprotocol/server-legacy 는 v1 의 서버 쪽 SSE 전송과 OAuth Authorization Server 도우미를 그대로 얼려 둔 복사본이에요. v1 배포가 모든 것을 한 번에 바꾸지 않고 v2 로 옮길 수 있도록 발행된 거죠. @modelcontextprotocol/codemod 는 v1 의 import 와 호출 지점을 v2 형태로 다시 써 주는 커맨드라인 도구입니다. 둘 다 새 프로젝트에 들어갈 물건이 아니에요 — 업그레이드 가이드에서 둘 다 다룹니다.

요약

  • 설치하는 패키지는 @modelcontextprotocol/server@modelcontextprotocol/client 둘이고, 프로토콜의 한쪽에 하나씩이에요.
  • 패키지 루트 엔트리는 런타임 중립이라, 프로세스를 띄우는 코드는 ./stdio 서브패스에 있고 import 할 때만 번들에 들어와요.
  • HTTP 어댑터 — node, express, hono, fastify — 는 createMcpHandler 위의 선택적 얇은 층이라 최대 하나만 설치하면 됩니다.
  • @modelcontextprotocol/core 는 Zod 스키마 상수만 내보내고, raw 와이어 JSON을 직접 검증하는 코드를 위한 거예요.
  • @modelcontextprotocol/server-legacy@modelcontextprotocol/codemod 는 새 프로젝트가 아니라 v1 에서 옮겨 올 때 쓰는 물건이에요.