
개인이 만든 MCP 서버를 공식 레지스트리에 공개하기까지 — npm publish와 mcp-publisher의 2단계 과정
요약
TypeScript 기반 MCP 서버를 npm과 공식 MCP 레지스트리에 배포하는 2단계 과정을 상세히 설명합니다. npm 패키지 발행 후 mcp-publisher를 통해 메타데이터를 등록하는 절차와 주의사항을 다룹니다.
핵심 포인트
- 배포는 npm publish와 mcp-publisher 등록의 2단계로 진행됨
- package.json과 server.json의 이름 일치가 필수적임
- version 정보는 package.json에서 동적으로 읽어오도록 구현 권장
- 배포의 핵심 가치는 발견 가능성(discoverability) 확보에 있음
TL;DR
- 개인적으로 TypeScript 기반의 MCP 서버를 제작하여, npm과 MCP 공식 레지스트리 (Model Context Protocol Registry) 양쪽 모두에 공개했다.
- 공개는 2단계로 이루어진다.
npm publish(패키지 본체) →mcp-publisher(레지스트리에 메타데이터 등록). - 주의할 점은 「
package.json.mcpName과server.json.name의 완전 일치」, 「server.json은 수동 동기화 필요」, 「description은 100자 이하」, 「npx캐시 문제」 등이다. - 그리고 솔직히 말해서: 레지스트리에 올라간다고 해서 그것만으로 사용자가 늘어나지는 않는다. 다운로드 수치는 미러 봇(mirror bot)으로 쉽게 부풀려질 수 있다. 가치는 '발견 가능성(discoverability)과 브랜드'라고 생각하는 것이 건강하다.
일본어로 「공식 레지스트리에 올리는 과정까지」를 다룬 글이 당시 거의 없었기에, 자신의 실례(19개 도구로 구성된 금융 계열 MCP 서버)를 소재로 절차를 정리한다.
전제: 어떤 서버인가
- 언어: TypeScript (ES2022 / strict)
- SDK:
@modelcontextprotocol/sdk, 입력 스키마는zod사용 - 트랜스포트 (Transport): stdio (Claude Desktop / Claude Code / Cursor에서
npx로 실행) - 규모: 19개 도구 (자산 형성 시뮬레이션, 시장 상황 스냅샷, 경제 지표 캘린더, 중앙은행 발언, 지정학)
도구의 「내용」(외부 API를 호출하는 로직)은 본 주제가 아니다. 여기서는 배포의 골격에 집중한다.
도구 등록의 최소 형태
MCP 서버의 본체는 놀라울 정도로 가볍다. 각 도구를 「5개의 프로퍼티를 가진 정직한 객체」로 만들고, 배열을 루프 돌며 등록하기만 하면 된다.
// tools/types.ts — 공통 타입과 응답 헬퍼
import type { ZodRawShape } from "zod";
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
...
// tools/calculate-compound-interest.ts — 도구 1개의 실체
import { z } from "zod";
import { jsonReply, type Tool } from "./types.js";
...
// index.ts — 엔트리. 배열을 루프로 registerTool
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
...
포인트는 serverInfo.version을 package.json에서 동적으로 읽어오는 것이다. 이를 수행하지 않으면, 릴리스할 때마다 버전을 하드코딩(hard-code)한 부분을 수정하는 것을 잊어 사고가 발생한다 (나도 경험했다).
동작 확인 (publish 전에 이것만은 반드시 수행)
stdio에 JSON-RPC를 흘려보내 tools/list가 반환되는지 확인한다.
npm run build
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"smoke","version":"0.0.1"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
...
응답에 도구들이 전부 나열되면 OK.
제1단계: npm publish
package.json에서 배포에 영향을 주는 부분은 주로 다음과 같다.
{
"name": "lit-forge-mcp",
"version": "0.20.0",
...
공개:
npm version patch # 버전을 올림
npm publish --otp=XXXXXX # 2FA(2단계 인증)가 활성화된 경우 OTP(Authenticator의 6자리 숫자) 필수
prepublishOnly에 빌드와 검증을 설정해 두면, "dist가 오래된 상태로 publish"되는 사고를 방지할 수 있다. files를 제한하지 않으면 node_modules까지 포함되므로 주의해야 한다.
제2단계: mcp-publisher로 공식 레지스트리(Official Registry)에 등록
이 부분이 일본어 정보가 매우 적은 구간이다. 레지스트리는 server.json을 읽는다.
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "io.github.noblabs/lit-forge-mcp",
...
}
공개 명령어:
mcp-publisher login github # 최초 실행 시 또는 토큰 만료 시. 대화형 TTY가 필요함
mcp-publisher publish
name이 io.github.<GitHub 사용자명>/<...> 네임스페이스(Namespace)로 되어 있으며, login github를 통해 소유권을 증명하는 구조다. 따라서 GitHub 계정과 패키지 네임스페이스가 연결된다.
주의할 점 (실제로 실수했던 순서)
package.json.mcpName과server.json.name불일치: 두 값이 완전히 일치해야 한다. 한쪽만 수정하고 publish하면 거부된다.server.json의 버전 수동 동기화:npm version을 올려도server.json은 자동으로 따라오지 않는다.version과packages[0].version두 곳을 수동으로 맞춰야 한다.server.json.description길이 제한: 긴 설명을 그대로 붙여넣으면 통과되지 않는다.server.json.description은 100자 이하여야 한다.npx캐시 문제: 클라이언트 설정을npx캐시인lit-forge-mcp라고만 적으면, 오래된 캐시 버전이 계속 사용될 수 있다.lit-forge-mcp@latest사용을 권장한다.- npm OTP 만료:
npm logout && npm login으로 다시 로그인해야 한다.
클라이언트 측 설정은 이것만 하면 된다:
# Claude Code
claude mcp add lit-forge -- npx -y lit-forge-mcp@latest
솔직한 이야기: 등록된다고 해서 그것만으로 사용자가 늘지는 않는다
이 부분이 가장 쓰고 싶었던 내용이다.
공식 레지스트리와 npm에 등록하면 Weekly Downloads나 GitHub clone 숫자가 움직이기 시작한다. 하지만 **그 대부분은 미러 봇(Mirror bot)과 레지스트리 크롤러(Crawler)**이며, 실제 사용자의 수치와는 완전히 다르다. 내 경우에도 실제로 사용하는 인원은 숫자가 보여주는 것보다 12단계(10100배) 정도 작다고 보고 있다.
따라서 "레지스트리 게재 = 사용자 확보"는 아니다. 게재를 통해 얻을 수 있는 것은 **발견성(검색 및 목록 노출)과 브랜드(공개 실적)**이며, 그 이후의 이용은 콘텐츠의 가치와 문서(Documentation)에 달려 있다. 이 점을 솔직하게 가늠해 두지 않으면, 숫자에 일희일비하며 소모될 수 있다.
요약
- MCP 서버의 본체는 가볍다 (5개 프로퍼티 × 루프 등록). 어려운 것은 내부 로직과 배포 및 운영의 절차다.
- 공개는 npm publish → mcp-publisher의 2단계로 이루어진다.
mcpName일치,server.json수동 동기화,description100자 제한,npx @latest사용이 전형적인 걸림돌이다. - 공개 후의 숫자는 봇에 의한 수치 부풀리기를 전제로 냉정하게 읽어야 한다.
이후 내가 맞닥뜨린 문제는 "외부 데이터를 반환하는 MCP의 품질 보증" (API 유래의 날짜 불일치, 유형 오인 등을 어떻게 자동 검출할 것인가)과 "6개월 단위의 업데이트 운영"이었다. verify:* 스크립트 + vitest의 2단계 검증으로 사고를 방지하는 구현 방식과, 공개부터 운영까지의 전 과정을 한 권에 담은 책을 Zenn에서 준비 중이다. 공개하면 여기에 링크를 추가하겠다. 질문이나 지적은 언제든 환영한다. 대상 리포지토리는 io.github.noblabs/lit-forge-mcp (GitHub: noblabs)이다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기